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

原文地址:https://www.cnblogs.com/supheart/p/4259707.html