NetUdpServer.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Text;
  7. using HslCommunication.Core;
  8. using HslCommunication.Core.Net;
  9. namespace HslCommunication.Enthernet
  10. {
  11. /// <summary>
  12. /// Udp网络的服务器端类
  13. /// </summary>
  14. public class NetUdpServer : NetworkServerBase
  15. {
  16. /// <summary>
  17. /// 获取或设置一次接收时的数据长度,默认2KB数据长度
  18. /// </summary>
  19. public int ReceiveCacheLength { get; set; } = 2048;
  20. /// <summary>
  21. /// 根据指定的端口启动Upd侦听
  22. /// </summary>
  23. /// <param name="port"></param>
  24. public override void ServerStart( int port )
  25. {
  26. if (!IsStarted)
  27. {
  28. CoreSocket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
  29. //绑定网络地址
  30. CoreSocket.Bind( new IPEndPoint( IPAddress.Any, port ) );
  31. RefreshReceive( );
  32. LogNet?.WriteInfo( ToString(), StringResources.NetEngineStart );
  33. IsStarted = true;
  34. }
  35. }
  36. /// <summary>
  37. /// 关闭引擎的操作
  38. /// </summary>
  39. protected override void CloseAction( )
  40. {
  41. AcceptString = null;
  42. AcceptByte = null;
  43. base.CloseAction( );
  44. }
  45. /// <summary>
  46. /// 重新开始接收数据
  47. /// </summary>
  48. /// <exception cref="ArgumentNullException"></exception>
  49. ///
  50. private void RefreshReceive( )
  51. {
  52. AppSession session = new AppSession( );
  53. session.WorkSocket = CoreSocket;
  54. session.UdpEndPoint = new IPEndPoint( IPAddress.Any, 0 );
  55. session.BytesContent = new byte[ReceiveCacheLength];
  56. //WorkSocket.BeginReceiveFrom(state.BytesHead, 0, 8, SocketFlags.None, ref state.UdpEndPoint, new AsyncCallback(ReceiveAsyncCallback), state);
  57. CoreSocket.BeginReceiveFrom( session.BytesContent, 0, ReceiveCacheLength, SocketFlags.None, ref session.UdpEndPoint, new AsyncCallback( AsyncCallback ), session );
  58. }
  59. private void AsyncCallback( IAsyncResult ar )
  60. {
  61. if (ar.AsyncState is AppSession)
  62. {
  63. AppSession session = ar.AsyncState as AppSession;
  64. try
  65. {
  66. int received = session.WorkSocket.EndReceiveFrom( ar, ref session.UdpEndPoint );
  67. //释放连接关联
  68. session.WorkSocket = null;
  69. //马上开始重新接收,提供性能保障
  70. RefreshReceive( );
  71. //处理数据
  72. if (received >= HslProtocol.HeadByteLength)
  73. {
  74. //检测令牌
  75. if (CheckRemoteToken( session.BytesContent ))
  76. {
  77. session.IpEndPoint = (IPEndPoint)session.UdpEndPoint;
  78. int contentLength = BitConverter.ToInt32( session.BytesContent, HslProtocol.HeadByteLength - 4 );
  79. if (contentLength == received - HslProtocol.HeadByteLength)
  80. {
  81. byte[] head = new byte[HslProtocol.HeadByteLength];
  82. byte[] content = new byte[contentLength];
  83. Array.Copy( session.BytesContent, 0, head, 0, HslProtocol.HeadByteLength );
  84. if (contentLength > 0)
  85. {
  86. Array.Copy( session.BytesContent, 32, content, 0, contentLength );
  87. }
  88. //解析内容
  89. content = HslProtocol.CommandAnalysis( head, content );
  90. int protocol = BitConverter.ToInt32( head, 0 );
  91. int customer = BitConverter.ToInt32( head, 4 );
  92. //丢给数据中心处理
  93. DataProcessingCenter( session, protocol, customer, content );
  94. }
  95. else
  96. {
  97. //否则记录到日志
  98. LogNet?.WriteWarn( ToString(), $"接收到异常数据,应接收长度:{(BitConverter.ToInt32( session.BytesContent, 4 ) + 8)} 实际接收:{received}" );
  99. }
  100. }
  101. else
  102. {
  103. LogNet?.WriteWarn( ToString( ), StringResources.TokenCheckFailed );
  104. }
  105. }
  106. else
  107. {
  108. LogNet?.WriteWarn( ToString( ), $"接收到异常数据,长度不符合要求,实际接收:{received}" );
  109. }
  110. }
  111. catch (ObjectDisposedException ex)
  112. {
  113. //主程序退出的时候触发
  114. }
  115. catch (Exception ex)
  116. {
  117. LogNet?.WriteException( ToString( ), StringResources.SocketEndReceiveException, ex );
  118. //重新接收,此处已经排除掉了对象释放的异常
  119. RefreshReceive( );
  120. }
  121. finally
  122. {
  123. //state = null;
  124. }
  125. }
  126. }
  127. /***********************************************************************************************************
  128. *
  129. * 无法使用如下的字节头接收来确认网络传输,总是报错为最小
  130. *
  131. ***********************************************************************************************************/
  132. //private void ReceiveAsyncCallback(IAsyncResult ar)
  133. //{
  134. // if (ar.AsyncState is AsyncStateOne state)
  135. // {
  136. // try
  137. // {
  138. // state.AlreadyReceivedHead += state.WorkSocket.EndReceiveFrom(ar, ref state.UdpEndPoint);
  139. // if (state.AlreadyReceivedHead < state.HeadLength)
  140. // {
  141. // //接续接收头数据
  142. // WorkSocket.BeginReceiveFrom(state.BytesHead, state.AlreadyReceivedHead, state.HeadLength - state.AlreadyReceivedHead, SocketFlags.None,
  143. // ref state.UdpEndPoint, new AsyncCallback(ReceiveAsyncCallback), state);
  144. // }
  145. // else
  146. // {
  147. // //开始接收内容
  148. // int ReceiveLenght = BitConverter.ToInt32(state.BytesHead, 4);
  149. // if (ReceiveLenght > 0)
  150. // {
  151. // state.BytesContent = new byte[ReceiveLenght];
  152. // WorkSocket.BeginReceiveFrom(state.BytesContent, state.AlreadyReceivedContent, state.BytesContent.Length - state.AlreadyReceivedContent,
  153. // SocketFlags.None, ref state.UdpEndPoint, new AsyncCallback(ContentReceiveAsyncCallback), state);
  154. // }
  155. // else
  156. // {
  157. // //没有内容了
  158. // ThreadDealWithReveice(state, BitConverter.ToInt32(state.BytesHead, 0), state.BytesContent);
  159. // state = null;
  160. // RefreshReceive();
  161. // }
  162. // }
  163. // }
  164. // catch(Exception ex)
  165. // {
  166. // LogHelper.SaveError(StringResources.异步数据结束挂起发送出错, ex);
  167. // }
  168. // }
  169. //}
  170. //private void ContentReceiveAsyncCallback(IAsyncResult ar)
  171. //{
  172. // if (ar.AsyncState is AsyncStateOne state)
  173. // {
  174. // try
  175. // {
  176. // state.AlreadyReceivedContent += state.WorkSocket.EndReceiveFrom(ar, ref state.UdpEndPoint);
  177. // if (state.AlreadyReceivedContent < state.BytesContent.Length)
  178. // {
  179. // //还需要继续接收
  180. // WorkSocket.BeginReceiveFrom(state.BytesContent, state.AlreadyReceivedContent, state.BytesContent.Length - state.AlreadyReceivedContent,
  181. // SocketFlags.None, ref state.UdpEndPoint, new AsyncCallback(ContentReceiveAsyncCallback), state);
  182. // }
  183. // else
  184. // {
  185. // //接收完成了
  186. // ThreadDealWithReveice(state, BitConverter.ToInt32(state.BytesHead, 0), new byte[0]);
  187. // state = null;
  188. // RefreshReceive();
  189. // }
  190. // }
  191. // catch (Exception ex)
  192. // {
  193. // LogHelper.SaveError(StringResources.异步数据结束挂起发送出错, ex);
  194. // }
  195. // }
  196. //}
  197. #region 数据中心处理块
  198. /// <summary>
  199. /// 数据处理中心
  200. /// </summary>
  201. /// <param name="receive"></param>
  202. /// <param name="protocol"></param>
  203. /// <param name="customer"></param>
  204. /// <param name="content"></param>
  205. internal override void DataProcessingCenter( AppSession receive, int protocol, int customer, byte[] content )
  206. {
  207. if (protocol == HslProtocol.ProtocolUserBytes)
  208. {
  209. AcceptByte?.Invoke( receive, customer, content );
  210. }
  211. else if (protocol == HslProtocol.ProtocolUserString)
  212. {
  213. // 接收到文本数据
  214. string str = Encoding.Unicode.GetString( content );
  215. AcceptString?.Invoke( receive, customer, str );
  216. }
  217. }
  218. #endregion
  219. #region 事件委托块
  220. /// <summary>
  221. /// 当接收到文本数据的时候,触发此事件
  222. /// </summary>
  223. public event Action<AppSession, NetHandle, string> AcceptString;
  224. /// <summary>
  225. /// 当接收到字节数据的时候,触发此事件
  226. /// </summary>
  227. public event Action<AppSession, NetHandle, byte[]> AcceptByte;
  228. #endregion
  229. #region Object Override
  230. /// <summary>
  231. /// 获取本对象的字符串表示形式
  232. /// </summary>
  233. /// <returns></returns>
  234. public override string ToString( )
  235. {
  236. return "NetUdpServer";
  237. }
  238. #endregion
  239. }
  240. }