TcppServer.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using Azylee.Core.ThreadUtils.SleepUtils;
  2. using Azylee.Core.WindowsUtils.ConsoleUtils;
  3. using Azylee.Jsons;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace Azylee.YeahWeb.SocketUtils.TcpUtils
  12. {
  13. /// <summary>
  14. /// Tcp 服务工具
  15. /// </summary>
  16. public class TcppServer
  17. {
  18. const int ReceiveBufferSize = 1024;
  19. private List<byte> ReceiveByte = new List<byte>();
  20. private int _Port = 52801;
  21. TcpListener Listener = null;
  22. Action<TcpClientInfo> OnConnectAction = null;
  23. Action<TcpClientInfo> OnDisconnectAction = null;
  24. Action<TcpClientInfo, TcpDataModel> OnReceiveAction = null;
  25. public TcpClientManager TcpClientManager = new TcpClientManager();
  26. /// <summary>
  27. /// 构造函数
  28. /// </summary>
  29. /// <param name="port">端口号</param>
  30. /// <param name="onConnect">连接动作</param>
  31. /// <param name="onDisconnect">断开动作</param>
  32. /// <param name="onReceive">接收消息</param>
  33. public TcppServer(int port, Action<TcpClientInfo> onConnect, Action<TcpClientInfo> onDisconnect, Action<TcpClientInfo, TcpDataModel> onReceive)
  34. {
  35. _Port = port;
  36. OnConnectAction = onConnect;
  37. OnDisconnectAction = onDisconnect;
  38. OnReceiveAction = onReceive;
  39. }
  40. #region 启动和停止服务
  41. /// <summary>
  42. /// 启动服务
  43. /// </summary>
  44. public void Start()
  45. {
  46. this.Listener = new TcpListener(IPAddress.Any, _Port);
  47. this.Listener.Start();
  48. this.Listener.BeginAcceptTcpClient(new AsyncCallback(acceptCallback), this.Listener);
  49. }
  50. /// <summary>
  51. /// 停止服务
  52. /// </summary>
  53. public void Stop()
  54. {
  55. foreach (var client in TcpClientManager.GetAll())
  56. {
  57. client?.Client?.Close();
  58. }
  59. Listener?.Stop();
  60. }
  61. #endregion
  62. #region 连接后的读写操作
  63. /// <summary>
  64. /// 发送数据
  65. /// </summary>
  66. /// <param name="host">主机地址</param>
  67. /// <param name="model">数据模型</param>
  68. public void Write(string host, TcpDataModel model)
  69. {
  70. var dictionary = TcpClientManager.GetInfoByHost(host);
  71. if (dictionary != null && dictionary.Client != null)
  72. {
  73. if (dictionary.Client.Connected)
  74. {
  75. TcpClientManager.UpdateUploadFlowCount(host, model.Data.Length);
  76. bool flag = TcpStreamHelper.Write(dictionary.Client, model);
  77. }
  78. }
  79. }
  80. /// <summary>
  81. /// 发送数据
  82. /// </summary>
  83. /// <param name="host">主机地址</param>
  84. /// <param name="type">类型</param>
  85. /// <param name="data">数据</param>
  86. public void Write(string host, int type, byte[] data)
  87. {
  88. Write(host, new TcpDataModel() { Type = type, Data = data });
  89. }
  90. /// <summary>
  91. /// 发送数据
  92. /// </summary>
  93. /// <param name="host">主机地址</param>
  94. /// <param name="type">类型</param>
  95. /// <param name="s">字符串</param>
  96. public void Write(string host, int type, string s)
  97. {
  98. Write(host, new TcpDataModel() { Type = type, Data = Json.Object2Byte(s) });
  99. }
  100. private void acceptCallback(IAsyncResult state)
  101. {
  102. try
  103. {
  104. TcpListener lstn = (TcpListener)state.AsyncState;
  105. TcpClient client = lstn.EndAcceptTcpClient(state);
  106. string host = client.Client.RemoteEndPoint.ToString();
  107. TcpClientManager.AddOrUpdate(host, client);
  108. ConnectTask(host, client);
  109. lstn.BeginAcceptTcpClient(new AsyncCallback(acceptCallback), lstn);
  110. }
  111. catch { }
  112. }
  113. private void ConnectTask(string host, TcpClient client)
  114. {
  115. TcpClientInfo clientInfo = TcpClientManager.GetInfoByHost(host);
  116. DateTime HeartbeatTime = DateTime.Now;
  117. //发送心跳
  118. Task.Factory.StartNew(() =>
  119. {
  120. while (client.Connected)
  121. {
  122. TcpDataModel model = new TcpDataModel() { Type = int.MaxValue };
  123. TcpStreamHelper.Write(client, model);
  124. Sleep.S(5);
  125. //if (DateTime.Now.AddSeconds(-10) > HeartbeatTime)
  126. // client.Close();
  127. Sleep.S(5);
  128. }
  129. });
  130. //接收消息
  131. Task.Factory.StartNew(() =>
  132. {
  133. OnConnectAction?.Invoke(clientInfo);//委托:已连接
  134. while (client.Connected)
  135. {
  136. try
  137. {
  138. TcpDataModel model = TcpStreamHelper.Read(client);
  139. if (model != null)
  140. {
  141. if (model.Type == int.MaxValue)
  142. {
  143. //过滤心跳
  144. HeartbeatTime = DateTime.Now;
  145. }
  146. else
  147. {
  148. TcpClientManager.UpdateDownloadFlowCount(host, model.Data.Length);
  149. OnReceiveAction(clientInfo, model);//委托:接收消息
  150. }
  151. }
  152. }
  153. catch { }
  154. //Sleep.S(1);
  155. }
  156. client.Close();
  157. TcpClientManager.RemoveByHost(host);
  158. OnDisconnectAction?.Invoke(clientInfo);//委托:断开连接
  159. });
  160. }
  161. #endregion
  162. }
  163. }