• C#的Socket简单实现消息发送


    Socket一般用于网络之间的通信,在这里,实现的是服务端与客户端的简单消息通信。
    首先是客户端的搭建,一般步骤是先建立Socket绑定本地的IP和端口,并对远端连接进行连接进行监听,这里的监听一般开启后台线程进行循环处理;如果远端有连接到本机的Socket的端口,则获取一个新的Socket对象并重新添加一个线程用于对远端地址进行消息通信(消息的收发),这样,服务端的Socket就简单实现,下面是winForm的具体实现。

    一、先建立Socket的服务类SocketServerManager,用于对Socket各种操作的统一管理:

     1     public class SocketManager
     2     {
     3         Socket _socket = null;
     4         EndPoint _endPoint = null;
     5         bool _isListening = false;
     6         int BACKLOG = 10;
     7 
     8         public SocketManager(string ip, int port)
     9         {
    10             _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    11             IPAddress _ip = IPAddress.Parse(ip);
    12             _endPoint = new IPEndPoint(_ip, port);
    13         }
    14 
    15         public void Start()
    16         {
    17             _socket.Bind(_endPoint); //绑定端口
    18             _socket.Listen(BACKLOG); //开启监听
    19             Thread acceptServer = new Thread(AcceptWork); //开启新线程处理监听
    20             acceptServer.IsBackground = true;
    21             _isListening = true;
    22             acceptServer.Start();
    23         }
    24 
    25         public void AcceptWork()
    26         {
    27             while (_isListening)
    28             {
    29                 Socket acceptSocket = _socket.Accept();
    30                 if (acceptSocket != null)
    31                 {
    32                     Thread socketConnectedThread = new Thread(newSocketReceive);
    33                     socketConnectedThread.IsBackground = true;
    34                     socketConnectedThread.Start(acceptSocket);
    35                 }
    36                 Thread.Sleep(200);
    37             }
    38         }
    39 
    40         public void newSocketReceive(object obj)
    41         {
    42             Socket socket = obj as Socket;
    43             while (true)
    44             {
    45                 try
    46                 {
    47                     if (socket == null) return;
    48                     //这里向系统投递一个接收信息的请求,并为其指定ReceiveCallBack做为回调函数 
    49                     socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, buffer);
    50                 }
    51                 catch (Exception ex)
    52                 {
    53                     return;
    54                 }
    55                 Thread.Sleep(100);
    56             }
    57         }
    58 
    59         private void ReceiveCallBack(IAsyncResult ar)
    60         {
    61         }
    62     }
    public class SockeServertManager

    上面是Socket管理类的模型,具体的方法是初始化和开启监听,接下来就是在Form的界面调用建立类和Start方法。

    客户端同样是初始化socket,然后就不是监听socket,而是调用Connect连接指定的Socket地址,最后是开启新的线程接收和发送消息。

     1     public class SocketClientManager
     2     {
     3         public Socket _socket = null;
     4         public EndPoint endPoint = null;
     5         public bool _isConnected = false;
     6 
     7         public SocketClientManager(string ip, int port)
     8         {
     9             IPAddress _ip = IPAddress.Parse(ip);
    10             endPoint = new IPEndPoint(_ip, port);
    11             _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    12         }
    13 
    14         public void Start()
    15         {
    16             _socket.BeginConnect(endPoint, ConnectedCallback, _socket);
    17             _isConnected = true;
    18             Thread socketClient = new Thread(SocketClientReceive);
    19             socketClient.IsBackground = true;
    20             socketClient.Start();
    21         }
    22 
    23         public void SocketClientReceive()
    24         {
    25             while (_isConnected)
    26             {
    27                 try {
    28                     _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, buffer);
    29                 }
    30                 catch (SocketException ex)
    31                 {
    32                     _isConnected = false;
    33                 }
    34                 
    35                 Thread.Sleep(100);
    36             }
    37         }
    38 
    39         public void ReceiveCallback(IAsyncResult ar)
    40         {
    41         }
    42     }
    public class SocketClientManager

    主要记住的是,客户端是监听Socket是固定的,是监听绑定地址的,每当有新的连接访问,则开启新的线程与之进行交互,而客户端只简单实现与服务端交互,服务端则只有一个。
    Socket的进行发送与接收,一般是通过异步方法BeginReceive和BeginSend进行处理,方法一般带有回调函数,用于执行操作之后的处理。
    还有就是连接的关闭,每关闭一个连接,先要结束在Socket所在的线程方法,我这里的处理是停止掉死循环的函数调用,每当线程所在函数执行完毕,则线程自动销毁。之后就是关闭所连接的socket。


    下面是我程序的完整实现,为了方便socket的管理,我把服务器的所有与客户端对话的Socket统一用字典管理,并封装在SocketInfo的内部类中,消息的发送与接收必须先找到该连接socket。
    最后就是界面的调用,完成Socket的网络消息交互。


    下面是具体的实现及源码:

      1     public class SocketManager
      2     {
      3         public Dictionary<string,SocketInfo> _listSocketInfo = null;
      4         Socket _socket = null;
      5         public SocketInfo socketInfo = null;
      6         EndPoint _endPoint = null;
      7         bool _isListening = false;
      8         int BACKLOG = 10;
      9 
     10         public delegate void OnConnectedHandler(string clientIP);
     11         public event OnConnectedHandler OnConnected;
     12         public delegate void OnReceiveMsgHandler(string ip);
     13         public event OnReceiveMsgHandler OnReceiveMsg;
     14         public event OnReceiveMsgHandler OnDisConnected;
     15 
     16         public SocketManager(string ip, int port)
     17         {
     18             _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     19             IPAddress _ip = IPAddress.Parse(ip);
     20             _endPoint = new IPEndPoint(_ip, port);
     21             _listSocketInfo = new Dictionary<string, SocketInfo>();
     22         }
     23 
     24         public void Start()
     25         {
     26             _socket.Bind(_endPoint); //绑定端口
     27             _socket.Listen(BACKLOG); //开启监听
     28             Thread acceptServer = new Thread(AcceptWork); //开启新线程处理监听
     29             acceptServer.IsBackground = true;
     30             _isListening = true;
     31             acceptServer.Start();
     32         }
     33 
     34         public void AcceptWork()
     35         {
     36             while (_isListening)
     37             {
     38                 Socket acceptSocket = _socket.Accept();
     39                 if (acceptSocket != null && this.OnConnected != null)
     40                 {
     41                     SocketInfo sInfo = new SocketInfo();
     42                     sInfo.socket = acceptSocket;
     43                     _listSocketInfo.Add(acceptSocket.RemoteEndPoint.ToString(), sInfo);
     44                     OnConnected(acceptSocket.RemoteEndPoint.ToString());
     45                     Thread socketConnectedThread = new Thread(newSocketReceive);
     46                     socketConnectedThread.IsBackground = true;
     47                     socketConnectedThread.Start(acceptSocket);
     48                 }
     49                 Thread.Sleep(200);
     50             }
     51         }
     52 
     53         public void newSocketReceive(object obj)
     54         {
     55             Socket socket = obj as Socket;
     56             SocketInfo sInfo = _listSocketInfo[socket.RemoteEndPoint.ToString()];
     57             sInfo.isConnected = true;
     58             while (sInfo.isConnected)
     59             {
     60                 try
     61                 {
     62                     if (sInfo.socket == null) return;
     63                     //这里向系统投递一个接收信息的请求,并为其指定ReceiveCallBack做为回调函数 
     64                     sInfo.socket.BeginReceive(sInfo.buffer, 0, sInfo.buffer.Length, SocketFlags.None, ReceiveCallBack, sInfo.socket.RemoteEndPoint);
     65                 }
     66                 catch (Exception ex)
     67                 {
     68                     return;
     69                 }
     70                 Thread.Sleep(100);
     71             }
     72         }
     73 
     74         private void ReceiveCallBack(IAsyncResult ar)
     75         {
     76             EndPoint ep = ar.AsyncState as IPEndPoint;
     77             SocketInfo info = _listSocketInfo[ep.ToString()];
     78             int readCount = 0;
     79             try
     80             {
     81                 if (info.socket == null) return;
     82                 readCount = info.socket.EndReceive(ar);
     83             }catch(Exception ex){
     84                 return;
     85             }
     86             if (readCount > 0)
     87             {
     88                 //byte[] buffer = new byte[readCount];
     89                 //Buffer.BlockCopy(info.buffer, 0, buffer, 0, readCount);
     90                 if (readCount < info.buffer.Length)
     91                 {
     92                     byte[] newBuffer = new byte[readCount];
     93                     Buffer.BlockCopy(info.buffer, 0, newBuffer, 0, readCount);
     94                     info.msgBuffer = newBuffer;
     95                 }
     96                 else
     97                 {
     98                     info.msgBuffer = info.buffer;
     99                 }
    100                 string msgTip = Encoding.ASCII.GetString(info.msgBuffer);
    101                 if (msgTip == "faild")
    102                 {
    103                     info.isConnected = false;
    104                     if (this.OnDisConnected != null) OnDisConnected(info.socket.RemoteEndPoint.ToString());
    105                     _listSocketInfo.Remove(info.socket.RemoteEndPoint.ToString());
    106                     info.socket.Close();
    107                     return;
    108                 }
    109                 if (OnReceiveMsg != null) OnReceiveMsg(info.socket.RemoteEndPoint.ToString());
    110             }
    111         }
    112 
    113         public void SendMsg(string text, string endPoint)
    114         {
    115             if (_listSocketInfo.Keys.Contains(endPoint) && _listSocketInfo[endPoint] != null)
    116             {
    117                 _listSocketInfo[endPoint].socket.Send(Encoding.ASCII.GetBytes(text));
    118             }
    119         }
    120 
    121         public void Stop()
    122         {
    123             _isListening = false;
    124             foreach (SocketInfo s in _listSocketInfo.Values)
    125             {
    126                 s.socket.Close();
    127             }
    128         }
    129 
    130         public class SocketInfo
    131         {
    132             public Socket socket = null;
    133             public byte[] buffer = null;
    134             public byte[] msgBuffer = null;
    135             public bool isConnected = false;
    136 
    137             public SocketInfo()
    138             {
    139                 buffer = new byte[1024 * 4];
    140             }
    141         }
    142     }
    public class SocketServerManager
     1     public class SocketClientManager
     2     {
     3         public Socket _socket = null;
     4         public EndPoint endPoint = null;
     5         public SocketInfo socketInfo = null;
     6         public bool _isConnected = false;
     7 
     8         public delegate void OnConnectedHandler();
     9         public event OnConnectedHandler OnConnected;
    10         public event OnConnectedHandler OnFaildConnect;
    11         public delegate void OnReceiveMsgHandler();
    12         public event OnReceiveMsgHandler OnReceiveMsg;
    13 
    14         public SocketClientManager(string ip, int port)
    15         {
    16             IPAddress _ip = IPAddress.Parse(ip);
    17             endPoint = new IPEndPoint(_ip, port);
    18             _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    19         }
    20 
    21         public void Start()
    22         {
    23             _socket.BeginConnect(endPoint, ConnectedCallback, _socket);
    24             _isConnected = true;
    25             Thread socketClient = new Thread(SocketClientReceive);
    26             socketClient.IsBackground = true;
    27             socketClient.Start();
    28         }
    29 
    30         public void SocketClientReceive()
    31         {
    32             while (_isConnected)
    33             {
    34                 SocketInfo info = new SocketInfo();
    35                 try {
    36                     _socket.BeginReceive(info.buffer, 0, info.buffer.Length, SocketFlags.None, ReceiveCallback, info);
    37                 }
    38                 catch (SocketException ex)
    39                 {
    40                     _isConnected = false;
    41                 }
    42                 
    43                 Thread.Sleep(100);
    44             }
    45         }
    46 
    47         public void ReceiveCallback(IAsyncResult ar)
    48         {
    49             socketInfo = ar.AsyncState as SocketInfo;
    50             if (this.OnReceiveMsg != null) OnReceiveMsg();
    51         }
    52 
    53         public void ConnectedCallback(IAsyncResult ar)
    54         {
    55             Socket socket = ar.AsyncState as Socket;
    56             if (socket.Connected)
    57             {
    58                 if (this.OnConnected != null) OnConnected();
    59             }
    60             else
    61             {
    62                 if (this.OnFaildConnect != null) OnFaildConnect();
    63             }
    64         }
    65 
    66         public void SendMsg(string msg)
    67         {
    68             byte[] buffer = Encoding.ASCII.GetBytes(msg);
    69             _socket.Send(buffer);
    70         }
    71 
    72         public class SocketInfo
    73         {
    74             public Socket socket = null;
    75             public byte[] buffer = null;
    76 
    77             public SocketInfo()
    78             {
    79                 buffer = new byte[1024 * 4];
    80             }
    81         }
    82     }
    public class SocketClientManager

     

    具体源码(.net4.5,vs2013):具体源码 https://files.cnblogs.com/files/supheart/ServerBySocket.zip

  • 相关阅读:
    工业相机基础知识
    软件测试最常用的 SQL 命令 | 掌握基本查询、条件查询、聚合查询
    一文掌握软件测试常用SQL命令
    PageObject设计模式在 UI 自动化中的实践(QQ 邮箱登陆为例)
    测试开发必备--搞定PO设计模式
    Junit5 + YAML 参数化和数据驱动,让 App 自动化测试更高效(一)
    快速搞定APP移动端自动化测试
    接口自动化测试的 “能” 与 “不能”
    如何精通接口测试?
    测试开发必备:Dubbo-admin+Zookeeper 的环境搭建实操
  • 原文地址:https://www.cnblogs.com/supheart/p/4259707.html
Copyright © 2020-2023  润新知