NetSupport.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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.IO;
  8. using System.Threading;
  9. using HslCommunication.BasicFramework;
  10. using HslCommunication.Enthernet;
  11. using HslCommunication.LogNet;
  12. namespace HslCommunication.Core
  13. {
  14. /*******************************************************************************
  15. *
  16. * 网络通信类的基础类,提供所有相关的基础方法和功能
  17. *
  18. * Network communication base class of the class, provides the basis of all relevant methods and functions
  19. *
  20. *******************************************************************************/
  21. #region 网络传输辅助类
  22. /// <summary>
  23. /// 静态的方法支持类,提供一些网络的静态支持
  24. /// </summary>
  25. public static class NetSupport
  26. {
  27. /// <summary>
  28. /// Socket传输中的缓冲池大小
  29. /// </summary>
  30. internal const int SocketBufferSize = 4096;
  31. /// <summary>
  32. /// 检查是否超时的静态方法
  33. /// </summary>
  34. /// <param name="timeout">数据封送对象</param>
  35. /// <param name="millisecond">超时的时间</param>
  36. internal static void ThreadPoolCheckConnect( HslTimeOut timeout, int millisecond )
  37. {
  38. while (!timeout.IsSuccessful)
  39. {
  40. if ((DateTime.Now - timeout.StartTime).TotalMilliseconds > millisecond)
  41. {
  42. // 连接超时或是验证超时
  43. if (!timeout.IsSuccessful) timeout.WorkSocket?.Close( );
  44. break;
  45. }
  46. Thread.Sleep( 100 );
  47. }
  48. }
  49. internal static void ThreadPoolCheckTimeOut( object obj )
  50. {
  51. if (obj is HslTimeOut)
  52. {
  53. HslTimeOut timeout = (HslTimeOut)obj;
  54. while (!timeout.IsSuccessful)
  55. {
  56. if ((DateTime.Now - timeout.StartTime).TotalMilliseconds > timeout.DelayTime)
  57. {
  58. // 连接超时或是验证超时
  59. if (!timeout.IsSuccessful)
  60. {
  61. timeout.Operator?.Invoke( );
  62. timeout.WorkSocket?.Close( );
  63. }
  64. break;
  65. }
  66. }
  67. }
  68. }
  69. /// <summary>
  70. /// 读取socket数据的基础方法,只适合用来接收指令头,或是同步数据
  71. /// </summary>
  72. /// <param name="socket">通信对象</param>
  73. /// <param name="receive">接收的长度</param>
  74. /// <returns></returns>
  75. /// <exception cref="ArgumentNullException"></exception>
  76. /// <exception cref="SocketException"></exception>
  77. /// <exception cref="ObjectDisposedException"></exception>
  78. /// <exception cref="System.Security.SecurityException"></exception>
  79. public static byte[] ReadBytesFromSocket( Socket socket, int receive )
  80. {
  81. return ReadBytesFromSocket( socket, receive, null, false, false );
  82. }
  83. /// <summary>
  84. /// 读取socket数据的基础方法,只适合用来接收指令头,或是同步数据
  85. /// </summary>
  86. /// <param name="socket">通信对象</param>
  87. /// <param name="receive">接收的长度</param>
  88. /// <param name="report">用于报告接收进度的对象</param>
  89. /// <param name="reportByPercent">是否按照百分比报告进度</param>
  90. /// <param name="response">是否回发接收数据长度</param>
  91. /// <returns></returns>
  92. /// <exception cref="ArgumentNullException"></exception>
  93. /// <exception cref="SocketException"></exception>
  94. /// <exception cref="ObjectDisposedException"></exception>
  95. /// <exception cref="System.Security.SecurityException"></exception>
  96. public static byte[] ReadBytesFromSocket( Socket socket, int receive, Action<long, long> report, bool reportByPercent, bool response )
  97. {
  98. byte[] bytes_receive = new byte[receive];
  99. int count_receive = 0;
  100. long percent = 0;
  101. while (count_receive < receive)
  102. {
  103. // 分割成2KB来接收数据
  104. int receive_length = (receive - count_receive) >= SocketBufferSize ? SocketBufferSize : (receive - count_receive);
  105. count_receive += socket.Receive( bytes_receive, count_receive, receive_length, SocketFlags.None );
  106. if (reportByPercent)
  107. {
  108. long percentCurrent = (long)count_receive * 100 / receive;
  109. if (percent != percentCurrent)
  110. {
  111. percent = percentCurrent;
  112. // 报告进度
  113. report?.Invoke( count_receive, receive );
  114. }
  115. }
  116. else
  117. {
  118. // 报告进度
  119. report?.Invoke( count_receive, receive );
  120. }
  121. // 回发进度
  122. if (response) socket.Send( BitConverter.GetBytes( (long)count_receive ) );
  123. }
  124. return bytes_receive;
  125. }
  126. /// <summary>
  127. /// 从socket套接字读取数据并写入流中,必然报告进度
  128. /// </summary>
  129. /// <param name="socket">通信对象</param>
  130. /// <param name="stream">stream</param>
  131. /// <param name="receive">接收的长度</param>
  132. /// <param name="report">用于报告接收进度的对象</param>
  133. /// <param name="reportByPercent">是否按照百分比报告进度</param>
  134. /// <returns></returns>
  135. /// <exception cref="ArgumentNullException"></exception>
  136. /// <exception cref="SocketException"></exception>
  137. /// <exception cref="ObjectDisposedException"></exception>
  138. /// <exception cref="System.Security.SecurityException"></exception>
  139. internal static void WriteStreamFromSocket( Socket socket, Stream stream, long receive, Action<long, long> report, bool reportByPercent )
  140. {
  141. byte[] buffer = new byte[SocketBufferSize];
  142. long count_receive = 0;
  143. long percent = 0;
  144. while (count_receive < receive)
  145. {
  146. // 分割成4KB来接收数据
  147. int current = socket.Receive( buffer, 0, SocketBufferSize, SocketFlags.None );
  148. count_receive += current;
  149. stream.Write( buffer, 0, current );
  150. if (reportByPercent)
  151. {
  152. long percentCurrent = count_receive * 100 / receive;
  153. if (percent != percentCurrent)
  154. {
  155. percent = percentCurrent;
  156. // 报告进度
  157. report?.Invoke( count_receive, receive );
  158. }
  159. }
  160. else
  161. {
  162. // 报告进度
  163. report?.Invoke( count_receive, receive );
  164. }
  165. // 回发进度
  166. socket.Send( BitConverter.GetBytes( count_receive ) );
  167. }
  168. buffer = null;
  169. }
  170. /// <summary>
  171. /// 读取流并将数据写入socket
  172. /// </summary>
  173. /// <param name="stream">文件流</param>
  174. /// <param name="socket">连接的套接字</param>
  175. /// <param name="length">返回的文件长度</param>
  176. /// <param name="report">发送的进度报告</param>
  177. /// <param name="reportByPercent"></param>
  178. /// <exception cref="SocketException"></exception>
  179. /// <exception cref="IOException"></exception>
  180. /// <exception cref="NotSupportedException"></exception>
  181. /// <exception cref="ObjectDisposedException"></exception>
  182. internal static void WriteSocketFromStream( Socket socket, Stream stream, long length, Action<long, long> report, bool reportByPercent )
  183. {
  184. byte[] buffer = new byte[SocketBufferSize];
  185. long count_send = 0;
  186. stream.Position = 0;
  187. long percent = 0;
  188. while (count_send < length)
  189. {
  190. int count = stream.Read( buffer, 0, SocketBufferSize );
  191. count_send += count;
  192. socket.Send( buffer, 0, count, SocketFlags.None );
  193. while (count_send != BitConverter.ToInt64( ReadBytesFromSocket( socket, 8 ), 0 )) ;
  194. long received = count_send;
  195. if (reportByPercent)
  196. {
  197. long percentCurrent = received * 100 / length;
  198. if (percent != percentCurrent)
  199. {
  200. percent = percentCurrent;
  201. // 报告进度
  202. report?.Invoke( received, length );
  203. }
  204. }
  205. else
  206. {
  207. // 报告进度
  208. report?.Invoke( received, length );
  209. }
  210. // 双重接收验证
  211. if (count == 0)
  212. {
  213. break;
  214. }
  215. }
  216. buffer = null;
  217. }
  218. }
  219. #endregion
  220. }