转自 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 }
来源:oschina
链接:https://my.oschina.net/u/4352960/blog/4348273