转自 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 }