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 == "\0\0\0faild")
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):具體源碼 http://files.cnblogs.com/files/supheart/ServerBySocket.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM