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 }
上面是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 }
主要記住的是,客戶端是監聽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 }

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 }
具體源碼(.net4.5,vs2013):具體源碼 http://files.cnblogs.com/files/supheart/ServerBySocket.zip