TcppServer.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. TcpDelegate.ReceiveMessage ReceiveMessage;
  23. TcpDelegate.OnConnect OnConnect;
  24. TcpDelegate.OnDisconnect OnDisconnect;
  25. List<TcpClientDictionary> Clients = new List<TcpClientDictionary>();
  26. /// <summary>
  27. /// 构造函数
  28. /// </summary>
  29. /// <param name="port">端口号</param>
  30. /// <param name="receive">接收消息</param>
  31. /// <param name="connect">连接动作</param>
  32. /// <param name="disconnect">断开动作</param>
  33. public TcppServer(int port,
  34. TcpDelegate.ReceiveMessage receive,
  35. TcpDelegate.OnConnect connect,
  36. TcpDelegate.OnDisconnect disconnect)
  37. {
  38. _Port = port;
  39. ReceiveMessage += receive;
  40. OnConnect += connect;
  41. OnDisconnect += disconnect;
  42. }
  43. #region 启动和停止服务
  44. /// <summary>
  45. /// 启动服务
  46. /// </summary>
  47. public void Start()
  48. {
  49. this.Listener = new TcpListener(IPAddress.Any, _Port);
  50. this.Listener.Start();
  51. this.Listener.BeginAcceptTcpClient(new AsyncCallback(acceptCallback), this.Listener);
  52. }
  53. /// <summary>
  54. /// 停止服务
  55. /// </summary>
  56. public void Stop()
  57. {
  58. foreach (var client in Clients)
  59. {
  60. client?.Client?.Close();
  61. }
  62. Clients.Clear();
  63. this.Listener?.Stop();
  64. }
  65. #endregion
  66. #region 连接后的读写操作
  67. /// <summary>
  68. /// 发送数据
  69. /// </summary>
  70. /// <param name="host">主机地址</param>
  71. /// <param name="model">数据模型</param>
  72. public void Write(string host, TcpDataModel model)
  73. {
  74. var dictionary = Clients_Get(host);
  75. if (dictionary != null && dictionary.Client != null)
  76. {
  77. if (dictionary.Client.Connected)
  78. {
  79. bool flag = TcpStreamHelper.Write(dictionary.Client, model);
  80. }
  81. }
  82. }
  83. /// <summary>
  84. /// 发送数据
  85. /// </summary>
  86. /// <param name="host">主机地址</param>
  87. /// <param name="type">类型</param>
  88. /// <param name="data">数据</param>
  89. public void Write(string host, int type, byte[] data)
  90. {
  91. Write(host, new TcpDataModel() { Type = type, Data = data });
  92. }
  93. /// <summary>
  94. /// 发送数据
  95. /// </summary>
  96. /// <param name="host">主机地址</param>
  97. /// <param name="type">类型</param>
  98. /// <param name="s">字符串</param>
  99. public void Write(string host, int type, string s)
  100. {
  101. Write(host, new TcpDataModel() { Type = type, Data = Json.Object2Byte(s) });
  102. }
  103. private void acceptCallback(IAsyncResult state)
  104. {
  105. try
  106. {
  107. TcpListener lstn = (TcpListener)state.AsyncState;
  108. TcpClient client = lstn.EndAcceptTcpClient(state);
  109. string host = client.Client.RemoteEndPoint.ToString();
  110. Clients_Add_Update(host, client);
  111. ConnectTask(host, client);
  112. lstn.BeginAcceptTcpClient(new AsyncCallback(acceptCallback), lstn);
  113. }
  114. catch { }
  115. }
  116. private void ConnectTask(string host, TcpClient client)
  117. {
  118. DateTime HeartbeatTime = DateTime.Now;
  119. //发送心跳
  120. Task.Factory.StartNew(() =>
  121. {
  122. while (client.Connected)
  123. {
  124. TcpDataModel model = new TcpDataModel() { Type = int.MaxValue };
  125. TcpStreamHelper.Write(client, model);
  126. Sleep.S(5);
  127. //if (DateTime.Now.AddSeconds(-10) > HeartbeatTime)
  128. // client.Close();
  129. Sleep.S(5);
  130. }
  131. });
  132. //接收消息
  133. Task.Factory.StartNew(() =>
  134. {
  135. OnConnect?.Invoke(host);//委托:已连接
  136. while (client.Connected)
  137. {
  138. try
  139. {
  140. TcpDataModel model = TcpStreamHelper.Read(client);
  141. if (model != null)
  142. {
  143. if (model.Type == int.MaxValue)
  144. {
  145. //过滤心跳
  146. HeartbeatTime = DateTime.Now;
  147. }
  148. else
  149. {
  150. ReceiveMessage(host, model);//委托:接收消息
  151. }
  152. }
  153. }
  154. catch { }
  155. //Sleep.S(1);
  156. }
  157. client.Close();
  158. Clients_Del(host);
  159. OnDisconnect?.Invoke(host);//委托:断开连接
  160. });
  161. }
  162. #endregion
  163. #region 连接的客户端列表维护
  164. /// <summary>
  165. /// 获取连接的客户端
  166. /// </summary>
  167. /// <returns></returns>
  168. private TcpClientDictionary Clients_Get(string host)
  169. {
  170. TcpClientDictionary client = null;
  171. try
  172. {
  173. client = Clients.FirstOrDefault(x => x.Host == host);
  174. }
  175. catch { }
  176. return client;
  177. }
  178. /// <summary>
  179. /// 添加或更新到客户端列表
  180. /// </summary>
  181. private void Clients_Add_Update(string host, TcpClient client)
  182. {
  183. try
  184. {
  185. var item = Clients.FirstOrDefault(x => x.Host == host);
  186. if (item == null)
  187. {
  188. Clients.Add(new TcpClientDictionary() { Host = host, Client = client });
  189. }
  190. else
  191. {
  192. item.Client = client;
  193. }
  194. }
  195. catch { }
  196. }
  197. /// <summary>
  198. /// 从客户端列表中删除
  199. /// </summary>
  200. private int Clients_Del(string host)
  201. {
  202. int count = 0;
  203. try
  204. {
  205. count = Clients.RemoveAll(x => x.Host == host);
  206. }
  207. catch { }
  208. return count;
  209. }
  210. /// <summary>
  211. /// 当前连接客户端总数
  212. /// </summary>
  213. /// <returns></returns>
  214. public int ClientsCount()
  215. {
  216. return Clients.Count();
  217. }
  218. #endregion
  219. }
  220. }