UdpSession.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. //------------------------------------------------------------------------------
  2. // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
  3. // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
  4. // CSDN博客:https://blog.csdn.net/qq_40374647
  5. // 哔哩哔哩视频:https://space.bilibili.com/94253567
  6. // Gitee源代码仓库:https://gitee.com/RRQM_Home
  7. // Github源代码仓库:https://github.com/RRQM
  8. // API首页:https://www.yuque.com/rrqm/touchsocket/index
  9. // 交流QQ群:234762506
  10. // 感谢您的下载和使用
  11. //------------------------------------------------------------------------------
  12. //------------------------------------------------------------------------------
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Net;
  16. using System.Net.Sockets;
  17. using System.Runtime.InteropServices;
  18. using System.Threading;
  19. using System.Threading.Tasks;
  20. using TouchSocket.Core;
  21. using TouchSocket.Resources;
  22. namespace TouchSocket.Sockets
  23. {
  24. /// <summary>
  25. /// 简单UDP会话。
  26. /// </summary>
  27. public class UdpSession : UdpSessionBase
  28. {
  29. /// <summary>
  30. /// 当收到数据时
  31. /// </summary>
  32. public UdpReceivedEventHandler Received { get; set; }
  33. /// <summary>
  34. /// <inheritdoc/>
  35. /// </summary>
  36. /// <param name="remoteEndPoint"></param>
  37. /// <param name="byteBlock"></param>
  38. /// <param name="requestInfo"></param>
  39. protected override void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
  40. {
  41. Received?.Invoke(remoteEndPoint, byteBlock, requestInfo);
  42. }
  43. }
  44. /// <summary>
  45. /// UDP基类服务器。
  46. /// </summary>
  47. public class UdpSessionBase : BaseSocket, IUdpSession, IPluginObject
  48. {
  49. private readonly ConcurrentList<SocketAsyncEventArgs> m_socketAsyncs;
  50. private TouchSocketConfig m_config;
  51. private UdpDataHandlingAdapter m_adapter;
  52. private NetworkMonitor m_monitor;
  53. private IPHost m_remoteIPHost;
  54. private ServerState m_serverState;
  55. private bool m_usePlugin;
  56. /// <summary>
  57. /// 构造函数
  58. /// </summary>
  59. public UdpSessionBase()
  60. {
  61. m_socketAsyncs = new ConcurrentList<SocketAsyncEventArgs>();
  62. Protocol = Protocol.UDP;
  63. Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  64. socket.ReceiveBufferSize = BufferLength;
  65. socket.SendBufferSize = BufferLength;
  66. m_monitor = new NetworkMonitor(null, socket);
  67. }
  68. /// <summary>
  69. /// 处理未经过适配器的数据。返回值表示是否继续向下传递。
  70. /// </summary>
  71. public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
  72. /// <summary>
  73. /// 处理经过适配器后的数据。返回值表示是否继续向下传递。
  74. /// </summary>
  75. public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
  76. /// <summary>
  77. /// <inheritdoc/>
  78. /// </summary>
  79. public bool CanSend => m_serverState == ServerState.Running;
  80. /// <summary>
  81. /// <inheritdoc/>
  82. /// </summary>
  83. public virtual bool CanSetDataHandlingAdapter => true;
  84. /// <summary>
  85. /// 获取配置
  86. /// </summary>
  87. public TouchSocketConfig Config => m_config;
  88. /// <summary>
  89. /// <inheritdoc/>
  90. /// </summary>
  91. public IContainer Container => m_config?.Container;
  92. /// <summary>
  93. /// <inheritdoc/>
  94. /// </summary>
  95. public DateTime LastReceivedTime { get; private set; }
  96. /// <summary>
  97. /// <inheritdoc/>
  98. /// </summary>
  99. public DateTime LastSendTime { get; private set; }
  100. /// <summary>
  101. /// 数据处理适配器
  102. /// </summary>
  103. public UdpDataHandlingAdapter DataHandlingAdapter => m_adapter;
  104. /// <summary>
  105. /// 监听器
  106. /// </summary>
  107. public NetworkMonitor Monitor => m_monitor;
  108. /// <summary>
  109. /// <inheritdoc/>
  110. /// </summary>
  111. public IPluginsManager PluginsManager => m_config?.PluginsManager;
  112. /// <summary>
  113. /// <inheritdoc/>
  114. /// </summary>
  115. public virtual Protocol Protocol { get; set; }
  116. /// <summary>
  117. /// 默认远程节点
  118. /// </summary>
  119. public IPHost RemoteIPHost => m_remoteIPHost;
  120. /// <summary>
  121. /// 服务器名称
  122. /// </summary>
  123. public string ServerName => Config?.GetValue(TouchSocketConfigExtension.ServerNameProperty);
  124. /// <summary>
  125. /// 获取服务器状态
  126. /// </summary>
  127. public ServerState ServerState => m_serverState;
  128. /// <summary>
  129. /// 是否已启用插件
  130. /// </summary>
  131. public bool UsePlugin => m_usePlugin;
  132. /// <summary>
  133. /// 退出组播
  134. /// </summary>
  135. /// <param name="multicastAddr"></param>
  136. public void DropMulticastGroup(IPAddress multicastAddr)
  137. {
  138. if (DisposedValue)
  139. {
  140. throw new ObjectDisposedException(GetType().FullName);
  141. }
  142. if (multicastAddr is null)
  143. {
  144. throw new ArgumentNullException(nameof(multicastAddr));
  145. }
  146. if (m_monitor.Socket.AddressFamily == AddressFamily.InterNetwork)
  147. {
  148. MulticastOption optionValue = new MulticastOption(multicastAddr);
  149. m_monitor.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, optionValue);
  150. }
  151. else
  152. {
  153. IPv6MulticastOption optionValue2 = new IPv6MulticastOption(multicastAddr);
  154. m_monitor.Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, optionValue2);
  155. }
  156. }
  157. /// <summary>
  158. /// 加入组播。
  159. /// <para>组播地址为 224.0.0.0 ~ 239.255.255.255,其中 224.0.0.0~224.255.255.255 不建议在用户程序中使用,因为它们一般都有特殊用途。</para>
  160. /// </summary>
  161. /// <param name="multicastAddr"></param>
  162. public void JoinMulticastGroup(IPAddress multicastAddr)
  163. {
  164. if (multicastAddr is null)
  165. {
  166. throw new ArgumentNullException(nameof(multicastAddr));
  167. }
  168. if (DisposedValue)
  169. {
  170. throw new ObjectDisposedException(GetType().FullName);
  171. }
  172. if (m_monitor.Socket.AddressFamily == AddressFamily.InterNetwork)
  173. {
  174. MulticastOption optionValue = new MulticastOption(multicastAddr);
  175. m_monitor.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, optionValue);
  176. }
  177. else
  178. {
  179. IPv6MulticastOption optionValue2 = new IPv6MulticastOption(multicastAddr);
  180. m_monitor.Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, optionValue2);
  181. }
  182. }
  183. /// <summary>
  184. /// 设置数据处理适配器
  185. /// </summary>
  186. /// <param name="adapter"></param>
  187. public virtual void SetDataHandlingAdapter(UdpDataHandlingAdapter adapter)
  188. {
  189. if (!CanSetDataHandlingAdapter)
  190. {
  191. throw new Exception($"不允许自由调用{nameof(SetDataHandlingAdapter)}进行赋值。");
  192. }
  193. SetAdapter(adapter);
  194. }
  195. /// <summary>
  196. /// <inheritdoc/>
  197. /// </summary>
  198. /// <param name="config"></param>
  199. /// <returns></returns>
  200. public IService Setup(TouchSocketConfig config)
  201. {
  202. m_config = config;
  203. if (config.IsUsePlugin)
  204. {
  205. PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
  206. }
  207. LoadConfig(m_config);
  208. if (UsePlugin)
  209. {
  210. PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
  211. }
  212. return this;
  213. }
  214. /// <summary>
  215. /// 通过端口配置
  216. /// </summary>
  217. /// <param name="port"></param>
  218. public IService Setup(int port)
  219. {
  220. TouchSocketConfig serverConfig = new TouchSocketConfig();
  221. serverConfig.SetBindIPHost(new IPHost(port));
  222. return Setup(serverConfig);
  223. }
  224. /// <summary>
  225. /// 启动服务
  226. /// </summary>
  227. public IService Start()
  228. {
  229. try
  230. {
  231. if (m_serverState == ServerState.Disposed)
  232. {
  233. throw new Exception("无法重新利用已释放对象");
  234. }
  235. switch (m_serverState)
  236. {
  237. case ServerState.None:
  238. {
  239. if (m_config.GetValue(TouchSocketConfigExtension.BindIPHostProperty) is IPHost iPHost)
  240. {
  241. BeginReceive(iPHost);
  242. }
  243. break;
  244. }
  245. case ServerState.Running:
  246. return this;
  247. case ServerState.Stopped:
  248. {
  249. if (m_config.GetValue(TouchSocketConfigExtension.BindIPHostProperty) is IPHost iPHost)
  250. {
  251. BeginReceive(iPHost);
  252. }
  253. break;
  254. }
  255. case ServerState.Disposed:
  256. {
  257. throw new Exception("无法再次利用已释放对象");
  258. }
  259. }
  260. m_serverState = ServerState.Running;
  261. if (UsePlugin)
  262. {
  263. PluginsManager.Raise<IServicePlugin>(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, default));
  264. }
  265. return this;
  266. }
  267. catch (Exception ex)
  268. {
  269. m_serverState = ServerState.Exception;
  270. if (UsePlugin)
  271. {
  272. PluginsManager.Raise<IServicePlugin>(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, ex) { Message = ex.Message }) ;
  273. }
  274. throw;
  275. }
  276. }
  277. /// <summary>
  278. /// 停止服务器
  279. /// </summary>
  280. public IService Stop()
  281. {
  282. m_monitor?.Socket.Dispose();
  283. m_monitor = null;
  284. m_serverState = ServerState.Stopped;
  285. foreach (var item in m_socketAsyncs)
  286. {
  287. item.SafeDispose();
  288. }
  289. m_socketAsyncs.Clear();
  290. if (UsePlugin)
  291. {
  292. PluginsManager.Raise<IServicePlugin>(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, default));
  293. }
  294. return this;
  295. }
  296. /// <summary>
  297. /// <inheritdoc/>
  298. /// </summary>
  299. /// <param name="disposing"></param>
  300. protected override void Dispose(bool disposing)
  301. {
  302. if (!this.DisposedValue)
  303. {
  304. if (disposing)
  305. {
  306. m_monitor?.Socket.Dispose();
  307. m_monitor = null;
  308. m_serverState = ServerState.Disposed;
  309. foreach (var item in m_socketAsyncs)
  310. {
  311. item.SafeDispose();
  312. }
  313. m_socketAsyncs.Clear();
  314. if (UsePlugin)
  315. {
  316. PluginsManager.Raise<IServicePlugin>(nameof(IServicePlugin.OnStarted), this, new ServiceStateEventArgs(this.m_serverState, default));
  317. }
  318. }
  319. }
  320. base.Dispose(disposing);
  321. }
  322. /// <summary>
  323. /// 处理已接收到的数据。
  324. /// </summary>
  325. /// <param name="remoteEndPoint"></param>
  326. /// <param name="byteBlock">以二进制流形式传递</param>
  327. /// <param name="requestInfo">以解析的数据对象传递</param>
  328. protected virtual void HandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
  329. {
  330. }
  331. /// <summary>
  332. /// 当即将发送时,如果覆盖父类方法,则不会触发插件。
  333. /// </summary>
  334. /// <param name="endPoint"></param>
  335. /// <param name="buffer">数据缓存区</param>
  336. /// <param name="offset">偏移</param>
  337. /// <param name="length">长度</param>
  338. /// <returns>返回值表示是否允许发送</returns>
  339. protected virtual bool HandleSendingData(EndPoint endPoint, byte[] buffer, int offset, int length)
  340. {
  341. return true;
  342. }
  343. /// <summary>
  344. /// 加载配置
  345. /// </summary>
  346. /// <param name="config"></param>
  347. protected virtual void LoadConfig(TouchSocketConfig config)
  348. {
  349. if (config == null)
  350. {
  351. throw new Exception("配置文件为空");
  352. }
  353. Logger = Container.Resolve<ILog>();
  354. m_remoteIPHost = config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
  355. BufferLength = config.GetValue(TouchSocketConfigExtension.BufferLengthProperty);
  356. m_usePlugin = config.IsUsePlugin;
  357. if (CanSetDataHandlingAdapter)
  358. {
  359. SetDataHandlingAdapter(Config.GetValue(TouchSocketConfigExtension.UdpDataHandlingAdapterProperty).Invoke());
  360. }
  361. }
  362. /// <summary>
  363. /// 在Socket初始化对象后,Bind之前调用。
  364. /// 可用于设置Socket参数。
  365. /// 父类方法可覆盖。
  366. /// </summary>
  367. /// <param name="socket"></param>
  368. protected virtual void PreviewBind(Socket socket)
  369. {
  370. }
  371. /// <summary>
  372. /// 设置适配器,该方法不会检验<see cref="CanSetDataHandlingAdapter"/>的值。
  373. /// </summary>
  374. /// <param name="adapter"></param>
  375. protected void SetAdapter(UdpDataHandlingAdapter adapter)
  376. {
  377. if (adapter is null)
  378. {
  379. throw new ArgumentNullException(nameof(adapter));
  380. }
  381. if (adapter.m_owner != null)
  382. {
  383. throw new Exception("此适配器已被其他终端使用,请重新创建对象。");
  384. }
  385. if (Config != null)
  386. {
  387. if (Config.GetValue(TouchSocketConfigExtension.MaxPackageSizeProperty) is int v1)
  388. {
  389. adapter.MaxPackageSize = v1;
  390. }
  391. }
  392. adapter.m_owner = this;
  393. adapter.ReceivedCallBack = PrivateHandleReceivedData;
  394. adapter.SendCallBack = DefaultSend;
  395. m_adapter = adapter;
  396. }
  397. private void BeginReceive(IPHost iPHost)
  398. {
  399. int threadCount = Config.GetValue(TouchSocketConfigExtension.ThreadCountProperty);
  400. threadCount = threadCount < 0 ? 1 : threadCount;
  401. Socket socket = new Socket(iPHost.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
  402. {
  403. ReceiveBufferSize = BufferLength,
  404. SendBufferSize = BufferLength,
  405. EnableBroadcast = m_config.GetValue(TouchSocketConfigExtension.EnableBroadcastProperty)
  406. };
  407. if (m_config.GetValue(TouchSocketConfigExtension.ReuseAddressProperty))
  408. {
  409. socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  410. }
  411. PreviewBind(socket);
  412. #region Windows下UDP连接被重置错误10054
  413. #if NET45_OR_GREATER
  414. const int SIP_UDP_CONNRESET = -1744830452;
  415. socket.IOControl(SIP_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
  416. #else
  417. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  418. {
  419. const int SIP_UDP_CONNRESET = -1744830452;
  420. socket.IOControl(SIP_UDP_CONNRESET, new byte[] { 0, 0, 0, 0 }, null);
  421. }
  422. #endif
  423. #endregion
  424. socket.Bind(iPHost.EndPoint);
  425. m_monitor = new NetworkMonitor(iPHost, socket);
  426. switch (m_config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty))
  427. {
  428. case ReceiveType.Auto:
  429. {
  430. #if NET45_OR_GREATER||NET5_0_OR_GREATER
  431. for (int i = 0; i < threadCount; i++)
  432. {
  433. SocketAsyncEventArgs eventArg = new SocketAsyncEventArgs();
  434. m_socketAsyncs.Add(eventArg);
  435. eventArg.Completed += IO_Completed;
  436. ByteBlock byteBlock = new ByteBlock(BufferLength);
  437. eventArg.UserToken = byteBlock;
  438. eventArg.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
  439. eventArg.RemoteEndPoint = iPHost.EndPoint;
  440. if (!socket.ReceiveFromAsync(eventArg))
  441. {
  442. ProcessReceive(socket, eventArg);
  443. }
  444. }
  445. #else
  446. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  447. {
  448. for (int i = 0; i < threadCount; i++)
  449. {
  450. SocketAsyncEventArgs eventArg = new SocketAsyncEventArgs();
  451. m_socketAsyncs.Add(eventArg);
  452. eventArg.Completed += IO_Completed;
  453. ByteBlock byteBlock = new ByteBlock(BufferLength);
  454. eventArg.UserToken = byteBlock;
  455. eventArg.SetBuffer(byteBlock.Buffer, 0, byteBlock.Capacity);
  456. eventArg.RemoteEndPoint = iPHost.EndPoint;
  457. if (!socket.ReceiveFromAsync(eventArg))
  458. {
  459. ProcessReceive(socket, eventArg);
  460. }
  461. }
  462. }
  463. else
  464. {
  465. Thread thread = new Thread(Received);
  466. thread.IsBackground = true;
  467. thread.Start();
  468. }
  469. #endif
  470. break;
  471. }
  472. default:
  473. throw new Exception("UDP中只支持Auto模式");
  474. }
  475. }
  476. private void Received()
  477. {
  478. while (true)
  479. {
  480. ByteBlock byteBlock = new ByteBlock();
  481. try
  482. {
  483. EndPoint endPoint = m_monitor.IPHost.EndPoint;
  484. int r = m_monitor.Socket.ReceiveFrom(byteBlock.Buffer, ref endPoint);
  485. byteBlock.SetLength(r);
  486. HandleBuffer(endPoint, byteBlock);
  487. }
  488. catch (Exception ex)
  489. {
  490. byteBlock.Dispose();
  491. Logger.Log(LogType.Error, this, ex.Message, ex);
  492. break;
  493. }
  494. }
  495. }
  496. private void HandleBuffer(EndPoint endPoint, ByteBlock byteBlock)
  497. {
  498. try
  499. {
  500. LastReceivedTime = DateTime.Now;
  501. if (OnHandleRawBuffer?.Invoke(byteBlock) == false)
  502. {
  503. return;
  504. }
  505. if (DisposedValue)
  506. {
  507. return;
  508. }
  509. if (m_adapter == null)
  510. {
  511. Logger.Error(this, TouchSocketStatus.NullDataAdapter.GetDescription());
  512. return;
  513. }
  514. m_adapter.ReceivedInput(endPoint, byteBlock);
  515. }
  516. catch (Exception ex)
  517. {
  518. Logger.Log(LogType.Error, this, "在处理数据时发生错误", ex);
  519. }
  520. finally
  521. {
  522. byteBlock.Dispose();
  523. }
  524. }
  525. private void IO_Completed(object sender, SocketAsyncEventArgs e)
  526. {
  527. ProcessReceive((Socket)sender, e);
  528. }
  529. private void PrivateHandleReceivedData(EndPoint remoteEndPoint, ByteBlock byteBlock, IRequestInfo requestInfo)
  530. {
  531. if (OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
  532. {
  533. return;
  534. }
  535. if (m_usePlugin)
  536. {
  537. UdpReceivedDataEventArgs args = new UdpReceivedDataEventArgs(remoteEndPoint, byteBlock, requestInfo);
  538. PluginsManager.Raise<IUdpSessionPlugin>(nameof(IUdpSessionPlugin.OnReceivedData), this, args);
  539. if (args.Handled)
  540. {
  541. return;
  542. }
  543. }
  544. HandleReceivedData(remoteEndPoint, byteBlock, requestInfo);
  545. }
  546. #region 向默认远程同步发送
  547. /// <summary>
  548. /// 向默认终结点发送
  549. /// </summary>
  550. /// <param name="buffer"></param>
  551. /// <param name="offset"></param>
  552. /// <param name="length"></param>
  553. public virtual void Send(byte[] buffer, int offset, int length)
  554. {
  555. if (m_remoteIPHost == null)
  556. {
  557. throw new Exception("默认终结点为空");
  558. }
  559. Send(m_remoteIPHost.EndPoint, buffer, offset, length);
  560. }
  561. /// <summary>
  562. /// <inheritdoc/>
  563. /// </summary>
  564. /// <param name="requestInfo"></param>
  565. /// <exception cref="OverlengthException"></exception>
  566. /// <exception cref="Exception"></exception>
  567. public virtual void Send(IRequestInfo requestInfo)
  568. {
  569. if (DisposedValue)
  570. {
  571. return;
  572. }
  573. if (m_adapter == null)
  574. {
  575. throw new ArgumentNullException(nameof(DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
  576. }
  577. if (!m_adapter.CanSendRequestInfo)
  578. {
  579. throw new NotSupportedException($"当前适配器不支持对象发送。");
  580. }
  581. m_adapter.SendInput(requestInfo);
  582. }
  583. #endregion 向默认远程同步发送
  584. #region 向默认远程异步发送
  585. /// <summary>
  586. /// IOCP发送
  587. /// </summary>
  588. /// <param name="buffer"></param>
  589. /// <param name="offset"></param>
  590. /// <param name="length"></param>
  591. /// <exception cref="NotConnectedException"></exception>
  592. /// <exception cref="OverlengthException"></exception>
  593. /// <exception cref="Exception"></exception>
  594. public virtual Task SendAsync(byte[] buffer, int offset, int length)
  595. {
  596. return EasyTask.Run(() =>
  597. {
  598. Send(buffer, offset, length);
  599. });
  600. }
  601. /// <summary>
  602. /// <inheritdoc/>
  603. /// </summary>
  604. /// <param name="requestInfo"></param>
  605. /// <exception cref="OverlengthException"></exception>
  606. /// <exception cref="Exception"></exception>
  607. public virtual Task SendAsync(IRequestInfo requestInfo)
  608. {
  609. return EasyTask.Run(() =>
  610. {
  611. Send(requestInfo);
  612. });
  613. }
  614. #endregion 向默认远程异步发送
  615. #region 向设置的远程同步发送
  616. /// <summary>
  617. /// 向设置的远程同步发送
  618. /// </summary>
  619. /// <param name="remoteEP"></param>
  620. /// <param name="buffer"></param>
  621. /// <param name="offset"></param>
  622. /// <param name="length"></param>
  623. /// <exception cref="NotConnectedException"></exception>
  624. /// <exception cref="OverlengthException"></exception>
  625. /// <exception cref="Exception"></exception>
  626. public virtual void Send(EndPoint remoteEP, byte[] buffer, int offset, int length)
  627. {
  628. m_adapter.SendInput(remoteEP, buffer, offset, length);
  629. }
  630. #endregion 向设置的远程同步发送
  631. #region 向设置的远程异步发送
  632. /// <summary>
  633. /// 向设置的远程异步发送
  634. /// </summary>
  635. /// <param name="remoteEP"></param>
  636. /// <param name="buffer"></param>
  637. /// <param name="offset"></param>
  638. /// <param name="length"></param>
  639. /// <exception cref="NotConnectedException"></exception>
  640. /// <exception cref="OverlengthException"></exception>
  641. /// <exception cref="Exception"></exception>
  642. public virtual Task SendAsync(EndPoint remoteEP, byte[] buffer, int offset, int length)
  643. {
  644. return EasyTask.Run(() =>
  645. {
  646. Send(remoteEP, buffer, offset, length);
  647. });
  648. }
  649. #endregion 向设置的远程异步发送
  650. private void ProcessReceive(Socket socket, SocketAsyncEventArgs e)
  651. {
  652. if (m_serverState == ServerState.Running && e.SocketError == SocketError.Success)
  653. {
  654. ByteBlock byteBlock = (ByteBlock)e.UserToken;
  655. byteBlock.SetLength(e.BytesTransferred);
  656. HandleBuffer(e.RemoteEndPoint, byteBlock);
  657. ByteBlock newByteBlock = new ByteBlock(BufferLength);
  658. e.UserToken = newByteBlock;
  659. e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Buffer.Length);
  660. try
  661. {
  662. if (!socket.ReceiveFromAsync(e))
  663. {
  664. ProcessReceive(socket, e);
  665. }
  666. }
  667. catch (System.Exception ex)
  668. {
  669. Logger.Log(LogType.Error, this, ex.Message, ex);
  670. }
  671. }
  672. else
  673. {
  674. if (e.SocketError != SocketError.Success)
  675. {
  676. Logger?.Error(this, $"接收出现错误:{e.SocketError},错误代码:{(int)e.SocketError}");
  677. e.Dispose();
  678. }
  679. }
  680. }
  681. #region DefaultSend
  682. /// <summary>
  683. /// <inheritdoc/>
  684. /// </summary>
  685. /// <param name="buffer"></param>
  686. /// <param name="offset"></param>
  687. /// <param name="length"></param>
  688. public void DefaultSend(byte[] buffer, int offset, int length)
  689. {
  690. DefaultSend(m_remoteIPHost.EndPoint, buffer, offset, length);
  691. }
  692. /// <summary>
  693. /// <inheritdoc/>
  694. /// </summary>
  695. /// <param name="endPoint"></param>
  696. /// <param name="buffer"></param>
  697. /// <param name="offset"></param>
  698. /// <param name="length"></param>
  699. public void DefaultSend(EndPoint endPoint, byte[] buffer, int offset, int length)
  700. {
  701. if (HandleSendingData(endPoint, buffer, offset, length))
  702. {
  703. if (CanSend)
  704. {
  705. m_monitor.Socket.SendTo(buffer, offset, length, SocketFlags.None, endPoint);
  706. }
  707. LastSendTime = DateTime.Now;
  708. }
  709. }
  710. #endregion DefaultSend
  711. #region DefaultSendAsync
  712. /// <summary>
  713. /// <inheritdoc/>
  714. /// </summary>
  715. /// <param name="buffer"></param>
  716. /// <param name="offset"></param>
  717. /// <param name="length"></param>
  718. public Task DefaultSendAsync(byte[] buffer, int offset, int length)
  719. {
  720. return EasyTask.Run(() =>
  721. {
  722. DefaultSend(buffer, offset, length);
  723. });
  724. }
  725. /// <summary>
  726. /// <inheritdoc/>
  727. /// </summary>
  728. /// <param name="endPoint"></param>
  729. /// <param name="buffer"></param>
  730. /// <param name="offset"></param>
  731. /// <param name="length"></param>
  732. public Task DefaultSendAsync(EndPoint endPoint, byte[] buffer, int offset, int length)
  733. {
  734. return EasyTask.Run(() =>
  735. {
  736. DefaultSend(buffer, offset, length);
  737. });
  738. }
  739. #endregion DefaultSendAsync
  740. #region 组合发送
  741. /// <summary>
  742. /// <inheritdoc/>
  743. /// </summary>
  744. /// <param name="transferBytes"></param>
  745. public void Send(IList<ArraySegment<byte>> transferBytes)
  746. {
  747. Send(m_remoteIPHost.EndPoint, transferBytes);
  748. }
  749. /// <summary>
  750. /// <inheritdoc/>
  751. /// </summary>
  752. /// <param name="endPoint"></param>
  753. /// <param name="transferBytes"></param>
  754. public void Send(EndPoint endPoint, IList<ArraySegment<byte>> transferBytes)
  755. {
  756. if (m_adapter == null)
  757. {
  758. throw new ArgumentNullException(nameof(DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
  759. }
  760. if (!m_adapter.CanSplicingSend)
  761. {
  762. throw new NotSupportedException("该适配器不支持拼接发送");
  763. }
  764. m_adapter.SendInput(endPoint, transferBytes);
  765. }
  766. /// <summary>
  767. /// <inheritdoc/>
  768. /// </summary>
  769. /// <param name="transferBytes"></param>
  770. public Task SendAsync(IList<ArraySegment<byte>> transferBytes)
  771. {
  772. return EasyTask.Run(() =>
  773. {
  774. Send(transferBytes);
  775. });
  776. }
  777. /// <summary>
  778. /// <inheritdoc/>
  779. /// </summary>
  780. /// <param name="endPoint"></param>
  781. /// <param name="transferBytes"></param>
  782. public Task SendAsync(EndPoint endPoint, IList<ArraySegment<byte>> transferBytes)
  783. {
  784. return EasyTask.Run(() =>
  785. {
  786. Send(endPoint, transferBytes);
  787. });
  788. }
  789. #endregion 组合发送
  790. }
  791. }