SocketSend.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System.Net;
  2. using System;
  3. using System.Net.Sockets;
  4. using System.Threading;
  5. namespace IFramework.Net.Udp
  6. {
  7. internal class SocketSend : UdpSocket,IDisposable
  8. {
  9. #region variable
  10. private int maxCount = 0;
  11. private SocketTokenManager<SocketAsyncEventArgs> sendTokenManager = null;
  12. private SocketBufferManager sendBufferManager = null;
  13. private bool _isDisposed = false;
  14. #endregion
  15. #region structure
  16. /// <summary>
  17. /// 发送事件回调
  18. /// </summary>
  19. public event EventHandler<SocketAsyncEventArgs> SentEventHandler;
  20. public void Dispose()
  21. {
  22. Dispose(true);
  23. GC.SuppressFinalize(this);
  24. }
  25. protected virtual void Dispose(bool isDisposing)
  26. {
  27. if (_isDisposed) return;
  28. if (isDisposing)
  29. {
  30. DisposeSocketPool();
  31. socket.Dispose();
  32. sendBufferManager.Clear();
  33. _isDisposed = true;
  34. }
  35. }
  36. #endregion
  37. #region public method
  38. /// <summary>
  39. /// 初始化发送对象
  40. /// </summary>
  41. /// <param name="maxCountClient">客户端最大数</param>
  42. public SocketSend(int maxCountClient, int blockSize = 4096)
  43. : base(blockSize)
  44. {
  45. this.maxCount = maxCountClient;
  46. socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  47. socket.ReceiveTimeout = receiveTimeout;
  48. socket.SendTimeout = sendTimeout;
  49. sendTokenManager = new SocketTokenManager<SocketAsyncEventArgs>(maxCountClient);
  50. sendBufferManager = new SocketBufferManager(maxCountClient, blockSize);
  51. for (int i = 0; i < maxCount; ++i)
  52. {
  53. SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs
  54. {
  55. UserToken = socket
  56. };
  57. socketArgs.Completed += ClientSocket_Completed;
  58. sendBufferManager.SetBuffer(socketArgs);
  59. sendTokenManager.Set(socketArgs);
  60. }
  61. }
  62. public SocketSend(Socket socket, int maxCountClient, int blockSize = 4096)
  63. : base(blockSize)
  64. {
  65. this.maxCount = maxCountClient;
  66. base.socket = socket;
  67. sendTokenManager = new SocketTokenManager<SocketAsyncEventArgs>(maxCountClient);
  68. sendBufferManager = new SocketBufferManager(maxCountClient, blockSize);
  69. for (int i = 0; i < maxCount; ++i)
  70. {
  71. SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs
  72. {
  73. UserToken = base.socket
  74. };
  75. socketArgs.Completed += ClientSocket_Completed;
  76. sendBufferManager.SetBuffer(socketArgs);
  77. sendTokenManager.Set(socketArgs);
  78. }
  79. }
  80. /// <summary>
  81. /// 发送数据
  82. /// </summary>
  83. /// <param name="buffer"></param>
  84. /// <param name="offset"></param>
  85. /// <param name="size"></param>
  86. /// <param name="waiting"></param>
  87. /// <param name="remoteEP"></param>
  88. public bool Send(SegmentOffset dataSegment, IPEndPoint remoteEP, bool waiting)
  89. {
  90. try
  91. {
  92. bool isWillEvent = true;
  93. ArraySegment<byte>[] segItems = sendBufferManager.BufferToSegments(dataSegment.buffer, dataSegment.offset, dataSegment.size);
  94. foreach (var seg in segItems)
  95. {
  96. var tArgs = sendTokenManager.GetEmptyWait((retry) =>
  97. {
  98. return true;
  99. }, waiting);
  100. if (tArgs == null)
  101. throw new Exception("发送缓冲池已用完,等待回收超时...");
  102. tArgs.RemoteEndPoint = remoteEP;
  103. if (!sendBufferManager.WriteBuffer(tArgs, seg.Array, seg.Offset, seg.Count))
  104. {
  105. sendTokenManager.Set(tArgs);
  106. throw new Exception(string.Format("发送缓冲区溢出...buffer block max size:{0}", sendBufferManager.BlockSize));
  107. }
  108. isWillEvent &= socket.SendToAsync(tArgs);
  109. if (!isWillEvent)
  110. {
  111. ProcessSent(tArgs);
  112. }
  113. Thread.Sleep(5);
  114. }
  115. return isWillEvent;
  116. }
  117. catch (Exception ex)
  118. {
  119. throw ex;
  120. }
  121. }
  122. /// <summary>
  123. /// 同步发送数据
  124. /// </summary>
  125. /// <param name="data"></param>
  126. /// <param name="offset"></param>
  127. /// <param name="size"></param>
  128. /// <param name="remoteEP"></param>
  129. /// <returns></returns>
  130. public int SendSync(SegmentOffset dataSegment, IPEndPoint remoteEP)
  131. {
  132. return socket.SendTo(dataSegment.buffer, dataSegment.offset, dataSegment.size,
  133. SocketFlags.None, remoteEP);
  134. }
  135. #endregion
  136. #region private method
  137. /// <summary>
  138. /// 释放缓冲池
  139. /// </summary>
  140. private void DisposeSocketPool()
  141. {
  142. sendTokenManager.ClearToCloseArgs();
  143. }
  144. /// <summary>
  145. /// 处理发送的数据
  146. /// </summary>
  147. /// <param name="e"></param>
  148. private void ProcessSent(SocketAsyncEventArgs e)
  149. {
  150. sendTokenManager.Set(e);
  151. if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
  152. {
  153. if (SentEventHandler != null)
  154. {
  155. SentEventHandler(e.UserToken as Socket, e);
  156. }
  157. }
  158. }
  159. /// <summary>
  160. /// 完成发送事件
  161. /// </summary>
  162. /// <param name="sender"></param>
  163. /// <param name="e"></param>
  164. void ClientSocket_Completed(object sender, SocketAsyncEventArgs e)
  165. {
  166. switch (e.LastOperation)
  167. {
  168. case SocketAsyncOperation.SendTo:
  169. case SocketAsyncOperation.SendPackets:
  170. case SocketAsyncOperation.Send:
  171. ProcessSent(e);
  172. break;
  173. default:
  174. break;
  175. }
  176. }
  177. #endregion
  178. }
  179. }