轉自 https://www.cnblogs.com/kellen451/p/7127670.html
1 /* 2 * 3 * 該類用於管理tcp連接通訊 4 * 5 */ 6 7 using System; 8 using System.Collections.Generic; 9 using System.Net.Sockets; 10 using System.Threading; 11 using System.Net; 12 13 namespace Communication 14 { 15 /// <summary> 16 /// 服務端 17 /// </summary> 18 public class MyTcpServer 19 { 20 21 private Socket ServerSocket = null;//服務端 22 public Dictionary<string, MySession> dic_ClientSocket = new Dictionary<string, MySession>();//tcp客戶端字典 23 private Dictionary<string, Thread> dic_ClientThread = new Dictionary<string, Thread>();//線程字典,每新增一個連接就添加一條線程 24 private bool Flag_Listen = true;//監聽客戶端連接的標志 25 26 /// <summary> 27 /// 啟動服務 28 /// </summary> 29 /// <param name="port">端口號</param> 30 public bool OpenServer(int port) 31 { 32 try 33 { 34 Flag_Listen = true; 35 // 創建負責監聽的套接字,注意其中的參數; 36 ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 37 // 創建包含ip和端口號的網絡節點對象; 38 IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port); 39 try 40 { 41 // 將負責監聽的套接字綁定到唯一的ip和端口上; 42 ServerSocket.Bind(endPoint); 43 } 44 catch 45 { 46 return false; 47 } 48 // 設置監聽隊列的長度; 49 ServerSocket.Listen(100); 50 // 創建負責監聽的線程; 51 Thread Thread_ServerListen = new Thread(ListenConnecting); 52 Thread_ServerListen.IsBackground = true; 53 Thread_ServerListen.Start(); 54 55 return true; 56 } 57 catch 58 { 59 return false; 60 } 61 } 62 /// <summary> 63 /// 關閉服務 64 /// </summary> 65 public void CloseServer() 66 { 67 lock (dic_ClientSocket) 68 { 69 foreach (var item in dic_ClientSocket) 70 { 71 item.Value.Close();//關閉每一個連接 72 } 73 dic_ClientSocket.Clear();//清除字典 74 } 75 lock (dic_ClientThread) 76 { 77 foreach (var item in dic_ClientThread) 78 { 79 item.Value.Abort();//停止線程 80 } 81 dic_ClientThread.Clear(); 82 } 83 Flag_Listen = false; 84 //ServerSocket.Shutdown(SocketShutdown.Both);//服務端不能主動關閉連接,需要把監聽到的連接逐個關閉 85 if (ServerSocket != null) 86 ServerSocket.Close(); 87 88 } 89 /// <summary> 90 /// 監聽客戶端請求的方法; 91 /// </summary> 92 private void ListenConnecting() 93 { 94 while (Flag_Listen) // 持續不斷的監聽客戶端的連接請求; 95 { 96 try 97 { 98 Socket sokConnection = ServerSocket.Accept(); // 一旦監聽到一個客戶端的請求,就返回一個與該客戶端通信的 套接字; 99 // 將與客戶端連接的 套接字 對象添加到集合中; 100 string str_EndPoint = sokConnection.RemoteEndPoint.ToString(); 101 MySession myTcpClient = new MySession() { TcpSocket = sokConnection }; 102 //創建線程接收數據 103 Thread th_ReceiveData = new Thread(ReceiveData); 104 th_ReceiveData.IsBackground = true; 105 th_ReceiveData.Start(myTcpClient); 106 //把線程及客戶連接加入字典 107 dic_ClientThread.Add(str_EndPoint, th_ReceiveData); 108 dic_ClientSocket.Add(str_EndPoint, myTcpClient); 109 } 110 catch 111 { 112 113 } 114 Thread.Sleep(200); 115 } 116 } 117 /// <summary> 118 /// 接收數據 119 /// </summary> 120 /// <param name="sokConnectionparn"></param> 121 private void ReceiveData(object sokConnectionparn) 122 { 123 MySession tcpClient = sokConnectionparn as MySession; 124 Socket socketClient = tcpClient.TcpSocket; 125 bool Flag_Receive = true; 126 127 while (Flag_Receive) 128 { 129 try 130 { 131 // 定義一個2M的緩存區; 132 byte[] arrMsgRec = new byte[1024 * 1024 * 2]; 133 // 將接受到的數據存入到輸入 arrMsgRec中; 134 int length = -1; 135 try 136 { 137 length = socketClient.Receive(arrMsgRec); // 接收數據,並返回數據的長度; 138 } 139 catch 140 { 141 Flag_Receive = false; 142 // 從通信線程集合中刪除被中斷連接的通信線程對象; 143 string keystr = socketClient.RemoteEndPoint.ToString(); 144 dic_ClientSocket.Remove(keystr);//刪除客戶端字典中該socket 145 dic_ClientThread[keystr].Abort();//關閉線程 146 dic_ClientThread.Remove(keystr);//刪除字典中該線程 147 148 tcpClient = null; 149 socketClient = null; 150 break; 151 } 152 byte[] buf = new byte[length]; 153 Array.Copy(arrMsgRec, buf, length); 154 lock (tcpClient.m_Buffer) 155 { 156 tcpClient.AddQueue(buf); 157 } 158 } 159 catch 160 { 161 162 } 163 Thread.Sleep(100); 164 } 165 } 166 /// <summary> 167 /// 發送數據給指定的客戶端 168 /// </summary> 169 /// <param name="_endPoint">客戶端套接字</param> 170 /// <param name="_buf">發送的數組</param> 171 /// <returns></returns> 172 public bool SendData(string _endPoint, byte[] _buf) 173 { 174 MySession myT = new MySession(); 175 if (dic_ClientSocket.TryGetValue(_endPoint, out myT)) 176 { 177 myT.Send(_buf); 178 return true; 179 } 180 else 181 { 182 return false; 183 } 184 } 185 } 186 187 /// <summary> 188 /// 會話端 189 /// </summary> 190 public class MySession 191 { 192 public Socket TcpSocket;//socket對象 193 public List<byte> m_Buffer = new List<byte>();//數據緩存區 194 195 public MySession() 196 { 197 198 } 199 200 /// <summary> 201 /// 發送數據 202 /// </summary> 203 /// <param name="buf"></param> 204 public void Send(byte[] buf) 205 { 206 if (buf != null) 207 { 208 TcpSocket.Send(buf); 209 } 210 } 211 /// <summary> 212 /// 獲取連接的ip 213 /// </summary> 214 /// <returns></returns> 215 public string GetIp() 216 { 217 IPEndPoint clientipe = (IPEndPoint)TcpSocket.RemoteEndPoint; 218 string _ip = clientipe.Address.ToString(); 219 return _ip; 220 } 221 /// <summary> 222 /// 關閉連接 223 /// </summary> 224 public void Close() 225 { 226 TcpSocket.Shutdown(SocketShutdown.Both); 227 } 228 /// <summary> 229 /// 提取正確數據包 230 /// </summary> 231 public byte[] GetBuffer(int startIndex, int size) 232 { 233 byte[] buf = new byte[size]; 234 m_Buffer.CopyTo(startIndex, buf, 0, size); 235 m_Buffer.RemoveRange(0, startIndex + size); 236 return buf; 237 } 238 239 /// <summary> 240 /// 添加隊列數據 241 /// </summary> 242 /// <param name="buffer"></param> 243 public void AddQueue(byte[] buffer) 244 { 245 m_Buffer.AddRange(buffer); 246 } 247 /// <summary> 248 /// 清除緩存 249 /// </summary> 250 public void ClearQueue() 251 { 252 m_Buffer.Clear(); 253 } 254 } 255 }