TcpFunction.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. namespace StandardLibrary
  11. {
  12. /// <summary>
  13. /// TCP服务器类
  14. /// </summary>
  15. class Tcp_Server
  16. {
  17. #region 字段声明
  18. /// <summary>
  19. /// TCP服务器接收到客户端连接请求事件
  20. /// </summary>
  21. public Action<string, bool> TcpConnectEvent;
  22. /// <summary>
  23. /// TCP服务器接收到客户端发送消息事件
  24. /// </summary>
  25. public Action<string, byte[]> TcpReceiveEvent;
  26. /// <summary>
  27. /// 负责监听客户端连接请求的线程
  28. /// </summary>
  29. private Thread threadWatch = null;
  30. /// <summary>
  31. /// //服务器套接字
  32. /// </summary>
  33. private Socket socketWatch = null;
  34. /// <summary>
  35. /// //客户端IP与套接字的集合
  36. /// </summary>
  37. private Dictionary<string, Socket> dictSocket = new Dictionary<string, Socket>();
  38. /// <summary>
  39. /// //客户端IP与线程的集合
  40. /// </summary>
  41. private Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
  42. private string _serverIp = "127.0.0.1";
  43. private int _serverPort = 1234;
  44. #endregion
  45. public string ServerIp
  46. {
  47. get { return _serverIp; }
  48. set { _serverIp = value; }
  49. }
  50. public int ServerPort
  51. {
  52. get { return _serverPort; }
  53. set { _serverPort = value; }
  54. }
  55. /// <summary>
  56. /// 打开侦听
  57. /// </summary>
  58. /// <param name="listenIP">侦听的IP</param>
  59. /// <param name="listenPort">侦听的端口号</param>
  60. public bool OpenTcpListen()
  61. {
  62. try
  63. {
  64. socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建负责监听的套接字
  65. IPAddress address = IPAddress.Parse(_serverIp);//获得IP地址
  66. IPEndPoint endPoint = new IPEndPoint(address, _serverPort);//创建包含ip和端口号的网络节点对象
  67. socketWatch.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  68. socketWatch.Bind(endPoint);//将负责监听的套接字绑定到唯一的ip和端口上
  69. socketWatch.Listen(16);//设置侦听队列的长度,开始侦听
  70. threadWatch = new Thread(WatchConnecting);//创建负责侦听的线程
  71. threadWatch.IsBackground = true;//设置为后台线程
  72. threadWatch.Start();//启动线程
  73. return true;
  74. }
  75. catch (Exception e)
  76. {
  77. MessageBox.Show("异常:" + e.Message, "服务器侦听", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
  78. return false;
  79. }
  80. }
  81. /// <summary>
  82. /// 侦听客户端请求
  83. /// </summary>
  84. private void WatchConnecting()
  85. {
  86. while (true) //持续监听客户端的连接请求
  87. {
  88. // 开始监听客户端连接请求,Accept方法会阻断当前的线程
  89. Socket sokConnection = socketWatch.Accept(); //一旦监听到一个客户端的请求,就返回一个与该客户端通信的套接字
  90. string ip = sokConnection.RemoteEndPoint.ToString().Split(':')[0];
  91. if (!dictSocket.ContainsKey(ip)) dictSocket.Add(ip, sokConnection);//将客户端的IP对象添加到集合中
  92. else dictSocket[ip] = sokConnection;
  93. Thread thr = new Thread(ReceiveMsg);//创建处理客户端连接线程
  94. thr.IsBackground = true;//设置为后台线程
  95. thr.Start(sokConnection);//启动线程
  96. if (!dictThread.ContainsKey(ip)) dictThread.Add(ip, thr); //将新建的线程添加到线程的集合中
  97. else dictThread[ip] = thr;
  98. if (TcpConnectEvent != null) TcpConnectEvent(ip, true);//发布客户端连接成功消息
  99. }
  100. }
  101. /// <summary>
  102. /// 接收数据处理
  103. /// </summary>
  104. /// <param name="sokConnectionparn">客户端套接字</param>
  105. private void ReceiveMsg(object sokConnectionparn)
  106. {
  107. Socket sokClient = sokConnectionparn as Socket;//客户端套接字
  108. string ip = sokClient.RemoteEndPoint.ToString().Split(':')[0];
  109. try
  110. {
  111. while (true)
  112. {
  113. byte[] arrMsgRec = new byte[2048 * 1];//定义一个1k字节的接收缓存区
  114. int length = sokClient.Receive(arrMsgRec);//接收数据将数据存入arrMsgRec,返回数据的长度,并阻挡当前线程
  115. if (length > 0)//判断接收到的数据长度,如果大于0则表示数据正常,如果小于或等于0则表示客户端断开连接
  116. {
  117. byte[] rec = new byte[length];
  118. Array.Copy(arrMsgRec, rec, length);
  119. if (TcpReceiveEvent != null) TcpReceiveEvent(ip, rec);//发布接收客户端消息
  120. }
  121. else dictThread[ip].Abort();//释放线程
  122. }
  123. }
  124. catch (Exception)
  125. {
  126. if (dictSocket.ContainsKey(ip)) dictSocket.Remove(ip);//从通信套接字集合中删除被中断连接的通信套接字
  127. if (dictThread.ContainsKey(ip)) dictThread.Remove(ip);//从通信线程集合中删除被中断连接的通信线程对象
  128. if (TcpConnectEvent != null) TcpConnectEvent(ip, false);//发布客户端连接断开消息
  129. }
  130. }
  131. public void CloseTcpConnect(string ip)
  132. {
  133. if (dictSocket.ContainsKey(ip))
  134. {
  135. dictThread[ip].Abort();
  136. dictSocket[ip].Close();
  137. }
  138. }
  139. public void CloseTcpListen()
  140. {
  141. //socketWatch.Close();
  142. //socketWatch.Dispose();
  143. //threadWatch.Abort();
  144. }
  145. /// <summary>
  146. /// 发送消息
  147. /// </summary>
  148. /// <param name="IP">客户端IP地址</param>
  149. /// <param name="SendData">数据</param>
  150. public bool SendServerMsg(string IP, string SendData)
  151. {
  152. try
  153. {
  154. byte[] sendMsg = Encoding.ASCII.GetBytes(SendData);
  155. if (dictSocket.ContainsKey(IP)) dictSocket[IP].Send(sendMsg);//发送数据
  156. return true;
  157. }
  158. catch { return false; }
  159. }
  160. /// <summary>
  161. /// 发送消息
  162. /// </summary>
  163. /// <param name="IP">客户端IP地址</param>
  164. /// <param name="SendData">数据</param>
  165. public bool SendServerMsg(string IP, byte[] SendData)
  166. {
  167. try
  168. {
  169. if (dictSocket.ContainsKey(IP)) dictSocket[IP].Send(SendData);//发送数据
  170. return true;
  171. }
  172. catch { return false; }
  173. }
  174. }
  175. /// <summary>
  176. /// TCP客户端类
  177. /// </summary>
  178. class Tcp_Client
  179. {
  180. /// <summary>
  181. /// 接收消息事件
  182. /// </summary>
  183. public event Action<string> TcpReceiveEvent;
  184. /// <summary>
  185. /// 连接状态事件
  186. /// </summary>
  187. public event Action<bool> TcpConnectEvent;
  188. /// <summary>
  189. /// TCP客户端
  190. /// </summary>
  191. private Socket tcpClient;
  192. /// <summary>
  193. /// 接收消息线程
  194. /// </summary>
  195. private Thread receiveThread;
  196. private string _ip = "127.0.0.1";
  197. private int _port = 8500;
  198. /// <summary>
  199. /// 获取或设置远程服务端IP地址
  200. /// </summary>
  201. public string IP
  202. {
  203. get { return _ip; }
  204. set { _ip = value; }
  205. }
  206. /// <summary>
  207. /// 获取或设置远程服务端端口号
  208. /// </summary>
  209. public int Port
  210. {
  211. get { return _port; }
  212. set { _port = value; }
  213. }
  214. /// <summary>
  215. /// 打开连接
  216. /// </summary>
  217. /// <param name="ip"></param>
  218. /// <param name="port"></param>
  219. public bool OpenTcpConnect()
  220. {
  221. IPEndPoint IpEnd = new IPEndPoint(IPAddress.Parse(_ip), _port);
  222. tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  223. try
  224. {
  225. tcpClient.Connect(IpEnd);//发起TCP连接
  226. receiveThread = new Thread(ReceiveMsg);//实例化并启动接受消息线程
  227. receiveThread.IsBackground = true;//设置为后台线程
  228. receiveThread.Start();//启动线程
  229. if (TcpConnectEvent != null) TcpConnectEvent(true);//发布连接成功消息
  230. return true;
  231. }
  232. catch (Exception e)
  233. {
  234. if (TcpConnectEvent != null) TcpConnectEvent(false);//发布连接失败消息
  235. return false;
  236. }
  237. }
  238. /// <summary>
  239. /// 关闭连接
  240. /// </summary>
  241. public void CloseTcpConnect()
  242. {
  243. tcpClient.Close();//断开TCP连接
  244. receiveThread.Abort();//销毁接受消息的线程
  245. }
  246. /// <summary>
  247. /// 接收服务端发送的消息
  248. /// </summary>
  249. public void ReceiveMsg()
  250. {
  251. try
  252. {
  253. while (true)
  254. {
  255. byte[] getData = new byte[2048];//创建接受数据的字节流
  256. int length = tcpClient.Receive(getData, getData.Length, 0);
  257. if (length > 0)
  258. {
  259. byte[] rec = new byte[length];
  260. Array.Copy(getData, rec, length);
  261. string getMsg = Encoding.ASCII.GetString(rec);//将字节数组转换成文本形式
  262. if (TcpReceiveEvent != null) TcpReceiveEvent(getMsg);
  263. }
  264. else receiveThread.Abort();//释放线程
  265. }
  266. }
  267. catch (Exception e)//检测释放线程异常
  268. {
  269. if (TcpConnectEvent != null) TcpConnectEvent(false);//发布连接断开消息
  270. CloseTcpConnect();
  271. }
  272. }
  273. /// <summary>
  274. /// 发送消息给服务端
  275. /// </summary>
  276. /// <param name="msg">数据</param>
  277. public void SendMsg(string msg)
  278. {
  279. byte[] sendData = Encoding.ASCII.GetBytes(msg);//将要发送的文本转换为字符数组形式
  280. tcpClient.Send(sendData, sendData.Length, 0);
  281. }
  282. /// <summary>
  283. /// 发送消息给服务端
  284. /// </summary>
  285. /// <param name="msg">数据</param>
  286. public void SendMsg(byte[] msg)
  287. {
  288. tcpClient.Send(msg);
  289. }
  290. }
  291. }