TcpClient.cs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  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.IO;
  16. using System.Net.Security;
  17. using System.Net.Sockets;
  18. using System.Runtime.InteropServices;
  19. using System.Threading.Tasks;
  20. using TouchSocket.Core;
  21. using TouchSocket.Resources;
  22. namespace TouchSocket.Sockets
  23. {
  24. /// <summary>
  25. /// 简单TCP客户端
  26. /// </summary>
  27. public class TcpClient : TcpClientBase
  28. {
  29. /// <summary>
  30. /// 接收到数据
  31. /// </summary>
  32. public ReceivedEventHandler<TcpClient> Received { get; set; }
  33. /// <summary>
  34. /// 接收数据
  35. /// </summary>
  36. /// <param name="byteBlock"></param>
  37. /// <param name="requestInfo"></param>
  38. protected override void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
  39. {
  40. this.Received?.Invoke(this, byteBlock, requestInfo);
  41. base.HandleReceivedData(byteBlock, requestInfo);
  42. }
  43. }
  44. /// <summary>
  45. /// TCP客户端
  46. /// </summary>
  47. [System.Diagnostics.DebuggerDisplay("{IP}:{Port}")]
  48. public class TcpClientBase : BaseSocket, ITcpClient
  49. {
  50. /// <summary>
  51. /// 构造函数
  52. /// </summary>
  53. public TcpClientBase()
  54. {
  55. this.Protocol = Protocol.TCP;
  56. }
  57. #region 变量
  58. private DelaySender m_delaySender;
  59. private bool m_useDelaySender;
  60. private Stream m_workStream;
  61. #endregion 变量
  62. #region 事件
  63. /// <summary>
  64. /// 成功连接到服务器
  65. /// </summary>
  66. public MessageEventHandler<ITcpClient> Connected { get; set; }
  67. /// <summary>
  68. /// 准备连接的时候,此时已初始化Socket,但是并未建立Tcp连接
  69. /// </summary>
  70. public ConnectingEventHandler<ITcpClient> Connecting { get; set; }
  71. /// <summary>
  72. /// 断开连接。在客户端未设置连接状态时,不会触发
  73. /// </summary>
  74. public DisconnectEventHandler<ITcpClientBase> Disconnected { get; set; }
  75. /// <summary>
  76. /// <inheritdoc/>
  77. /// </summary>
  78. public DisconnectEventHandler<ITcpClientBase> Disconnecting { get; set; }
  79. private void PrivateOnConnected(MsgEventArgs e)
  80. {
  81. if (this.UsePlugin)
  82. {
  83. this.PluginsManager.Raise<IConnectedPlugin>(nameof(IConnectedPlugin.OnConnected), this, e);
  84. if (e.Handled)
  85. {
  86. return;
  87. }
  88. }
  89. this.OnConnected(e);
  90. }
  91. /// <summary>
  92. /// 已经建立Tcp连接
  93. /// </summary>
  94. /// <param name="e"></param>
  95. protected virtual void OnConnected(MsgEventArgs e)
  96. {
  97. try
  98. {
  99. this.Connected?.Invoke(this, e);
  100. }
  101. catch (System.Exception ex)
  102. {
  103. this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.Connected)}中发生错误。", ex);
  104. }
  105. }
  106. private void PrivateOnConnecting(ConnectingEventArgs e)
  107. {
  108. this.LastReceivedTime = DateTime.Now;
  109. this.LastSendTime = DateTime.Now;
  110. if (this.CanSetDataHandlingAdapter)
  111. {
  112. this.SetDataHandlingAdapter(this.Config.GetValue<Func<DataHandlingAdapter>>(TouchSocketConfigExtension.DataHandlingAdapterProperty).Invoke());
  113. }
  114. if (this.UsePlugin)
  115. {
  116. this.PluginsManager.Raise<IConnectingPlugin>(nameof(IConnectingPlugin.OnConnecting), this, e);
  117. if (e.Handled)
  118. {
  119. return;
  120. }
  121. }
  122. this.OnConnecting(e);
  123. }
  124. /// <summary>
  125. /// 准备连接的时候,此时已初始化Socket,但是并未建立Tcp连接
  126. /// </summary>
  127. /// <param name="e"></param>
  128. protected virtual void OnConnecting(ConnectingEventArgs e)
  129. {
  130. try
  131. {
  132. this.Connecting?.Invoke(this, e);
  133. }
  134. catch (Exception ex)
  135. {
  136. this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.OnConnecting)}中发生错误。", ex);
  137. }
  138. }
  139. private void PrivateOnDisconnected(DisconnectEventArgs e)
  140. {
  141. if (this.UsePlugin && this.PluginsManager.Raise<IDisconnectedPlguin>(nameof(IDisconnectedPlguin.OnDisconnected), this, e))
  142. {
  143. return;
  144. }
  145. this.OnDisconnected(e);
  146. }
  147. /// <summary>
  148. /// 断开连接。在客户端未设置连接状态时,不会触发
  149. /// </summary>
  150. /// <param name="e"></param>
  151. protected virtual void OnDisconnected(DisconnectEventArgs e)
  152. {
  153. try
  154. {
  155. this.Disconnected?.Invoke(this, e);
  156. }
  157. catch (Exception ex)
  158. {
  159. this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.Disconnected)}中发生错误。", ex);
  160. }
  161. }
  162. private void PrivateOnDisconnecting(DisconnectEventArgs e)
  163. {
  164. if (this.UsePlugin && this.PluginsManager.Raise<IDisconnectingPlugin>(nameof(IDisconnectingPlugin.OnDisconnecting), this, e))
  165. {
  166. return;
  167. }
  168. this.OnDisconnecting(e);
  169. }
  170. /// <summary>
  171. /// 即将断开连接(仅主动断开时有效)。
  172. /// <para>
  173. /// 当主动调用Close断开时,可通过<see cref="TouchSocketEventArgs.IsPermitOperation"/>终止断开行为。
  174. /// </para>
  175. /// </summary>
  176. /// <param name="e"></param>
  177. protected virtual void OnDisconnecting(DisconnectEventArgs e)
  178. {
  179. try
  180. {
  181. this.Disconnecting?.Invoke(this, e);
  182. }
  183. catch (Exception ex)
  184. {
  185. this.Logger.Log(LogType.Error, this, $"在事件{nameof(this.Disconnecting)}中发生错误。", ex);
  186. }
  187. }
  188. #endregion 事件
  189. #region 属性
  190. /// <summary>
  191. /// <inheritdoc/>
  192. /// </summary>
  193. public DateTime LastReceivedTime { get; private set; }
  194. /// <summary>
  195. /// <inheritdoc/>
  196. /// </summary>
  197. public DateTime LastSendTime { get; private set; }
  198. /// <summary>
  199. /// 处理未经过适配器的数据。返回值表示是否继续向下传递。
  200. /// </summary>
  201. public Func<ByteBlock, bool> OnHandleRawBuffer { get; set; }
  202. /// <summary>
  203. /// 处理经过适配器后的数据。返回值表示是否继续向下传递。
  204. /// </summary>
  205. public Func<ByteBlock, IRequestInfo, bool> OnHandleReceivedData { get; set; }
  206. /// <summary>
  207. /// <inheritdoc/>
  208. /// </summary>
  209. public IContainer Container => this.Config?.Container;
  210. /// <summary>
  211. /// <inheritdoc/>
  212. /// </summary>
  213. public virtual bool CanSetDataHandlingAdapter => true;
  214. /// <summary>
  215. /// 客户端配置
  216. /// </summary>
  217. public TouchSocketConfig Config { get; private set; }
  218. /// <summary>
  219. /// 数据处理适配器
  220. /// </summary>
  221. public DataHandlingAdapter DataHandlingAdapter { get; private set; }
  222. /// <summary>
  223. /// IP地址
  224. /// </summary>
  225. public string IP { get; private set; }
  226. /// <summary>
  227. /// 主通信器
  228. /// </summary>
  229. public Socket MainSocket { get; private set; }
  230. /// <summary>
  231. /// <inheritdoc/>
  232. /// </summary>
  233. public bool CanSend { get; private set; }
  234. /// <summary>
  235. /// <inheritdoc/>
  236. /// </summary>
  237. public bool Online => this.CanSend;
  238. /// <summary>
  239. /// <inheritdoc/>
  240. /// </summary>
  241. public IPluginsManager PluginsManager { get; private set; }
  242. /// <summary>
  243. /// 端口号
  244. /// </summary>
  245. public int Port { get; private set; }
  246. /// <summary>
  247. /// <inheritdoc/>
  248. /// </summary>
  249. public ReceiveType ReceiveType { get; private set; }
  250. /// <summary>
  251. /// 是否已启用插件
  252. /// </summary>
  253. public bool UsePlugin { get; private set; }
  254. /// <summary>
  255. /// <inheritdoc/>
  256. /// </summary>
  257. public bool UseSsl { get; private set; }
  258. /// <summary>
  259. /// <inheritdoc/>
  260. /// </summary>
  261. public Protocol Protocol { get; set; }
  262. /// <summary>
  263. /// <inheritdoc/>
  264. /// </summary>
  265. public IPHost RemoteIPHost { get; private set; }
  266. /// <inheritdoc/>
  267. public bool IsClient => true;
  268. #endregion 属性
  269. #region 断开操作
  270. /// <summary>
  271. /// <inheritdoc/>
  272. /// </summary>
  273. public virtual void Close()
  274. {
  275. this.Close($"{nameof(Close)}主动断开");
  276. }
  277. /// <summary>
  278. /// 中断终端,传递中断消息。
  279. /// </summary>
  280. /// <param name="msg"></param>
  281. public virtual void Close(string msg)
  282. {
  283. if (this.CanSend)
  284. {
  285. var args = new DisconnectEventArgs(true, msg)
  286. {
  287. IsPermitOperation = true
  288. };
  289. this.PrivateOnDisconnecting(args);
  290. if (this.DisposedValue || args.IsPermitOperation)
  291. {
  292. this.BreakOut(msg, true);
  293. }
  294. }
  295. }
  296. private void BreakOut(string msg, bool manual)
  297. {
  298. lock (this.SyncRoot)
  299. {
  300. if (this.CanSend)
  301. {
  302. this.CanSend = false;
  303. this.TryShutdown();
  304. this.MainSocket.SafeDispose();
  305. this.m_delaySender.SafeDispose();
  306. this.m_workStream.SafeDispose();
  307. this.DataHandlingAdapter.SafeDispose();
  308. this.PrivateOnDisconnected(new DisconnectEventArgs(manual, msg));
  309. }
  310. }
  311. }
  312. /// <summary>
  313. /// <inheritdoc/>
  314. /// </summary>
  315. /// <param name="disposing"></param>
  316. protected override void Dispose(bool disposing)
  317. {
  318. if (this.CanSend)
  319. {
  320. var args = new DisconnectEventArgs(true, $"{nameof(Dispose)}主动断开");
  321. this.PrivateOnDisconnecting(args);
  322. }
  323. this.PluginsManager?.Clear();
  324. this.Config = default;
  325. this.DataHandlingAdapter.SafeDispose();
  326. this.DataHandlingAdapter = default;
  327. this.BreakOut($"{nameof(Dispose)}主动断开", true);
  328. base.Dispose(disposing);
  329. }
  330. #endregion 断开操作
  331. /// <summary>
  332. /// 建立Tcp的连接。
  333. /// </summary>
  334. /// <param name="timeout"></param>
  335. /// <exception cref="ObjectDisposedException"></exception>
  336. /// <exception cref="ArgumentNullException"></exception>
  337. /// <exception cref="Exception"></exception>
  338. /// <exception cref="TimeoutException"></exception>
  339. protected void TcpConnect(int timeout)
  340. {
  341. lock (this.SyncRoot)
  342. {
  343. if (this.CanSend)
  344. {
  345. return;
  346. }
  347. if (this.DisposedValue)
  348. {
  349. throw new ObjectDisposedException(this.GetType().FullName);
  350. }
  351. if (this.Config == null)
  352. {
  353. throw new ArgumentNullException("配置文件不能为空。");
  354. }
  355. IPHost iPHost = this.Config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
  356. if (iPHost == null)
  357. {
  358. throw new ArgumentNullException("iPHost不能为空。");
  359. }
  360. if (this.MainSocket != null)
  361. {
  362. this.MainSocket.Dispose();
  363. }
  364. this.MainSocket = this.CreateSocket(iPHost);
  365. ConnectingEventArgs args = new ConnectingEventArgs(this.MainSocket);
  366. this.PrivateOnConnecting(args);
  367. if (timeout == 5000)
  368. {
  369. this.MainSocket.Connect(iPHost.EndPoint);
  370. this.CanSend = true;
  371. this.LoadSocketAndReadIpPort();
  372. if (this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption)
  373. {
  374. this.m_useDelaySender = true;
  375. this.m_delaySender.SafeDispose();
  376. this.m_delaySender = new DelaySender(this.MainSocket, senderOption.QueueLength, this.OnDelaySenderError)
  377. {
  378. DelayLength = senderOption.DelayLength
  379. };
  380. }
  381. this.BeginReceive();
  382. this.PrivateOnConnected(new MsgEventArgs("连接成功"));
  383. }
  384. else
  385. {
  386. var result = this.MainSocket.BeginConnect(iPHost.EndPoint, null, null);
  387. if (result.AsyncWaitHandle.WaitOne(timeout))
  388. {
  389. if (this.MainSocket.Connected)
  390. {
  391. this.MainSocket.EndConnect(result);
  392. this.CanSend = true;
  393. this.LoadSocketAndReadIpPort();
  394. if (this.Config.GetValue(TouchSocketConfigExtension.DelaySenderProperty) is DelaySenderOption senderOption)
  395. {
  396. this.m_useDelaySender = true;
  397. this.m_delaySender.SafeDispose();
  398. this.m_delaySender = new DelaySender(this.MainSocket, senderOption.QueueLength, this.OnDelaySenderError)
  399. {
  400. DelayLength = senderOption.DelayLength
  401. };
  402. }
  403. this.BeginReceive();
  404. this.PrivateOnConnected(new MsgEventArgs("连接成功"));
  405. return;
  406. }
  407. else
  408. {
  409. this.MainSocket.SafeDispose();
  410. throw new Exception("异步已完成,但是socket并未在连接状态,可能发生了绑定端口占用的错误。");
  411. }
  412. }
  413. this.MainSocket.SafeDispose();
  414. throw new TimeoutException();
  415. }
  416. }
  417. }
  418. /// <summary>
  419. /// 请求连接到服务器。
  420. /// </summary>
  421. public virtual ITcpClient Connect(int timeout = 5000)
  422. {
  423. this.TcpConnect(timeout);
  424. return this;
  425. }
  426. /// <summary>
  427. /// 异步连接服务器
  428. /// </summary>
  429. public Task<ITcpClient> ConnectAsync(int timeout = 5000)
  430. {
  431. return EasyTask.Run(() =>
  432. {
  433. return this.Connect(timeout);
  434. });
  435. }
  436. /// <summary>
  437. /// <inheritdoc/>
  438. /// </summary>
  439. /// <returns></returns>
  440. public Stream GetStream()
  441. {
  442. if (this.m_workStream == null)
  443. {
  444. this.m_workStream = new NetworkStream(this.MainSocket, true);
  445. }
  446. return this.m_workStream;
  447. }
  448. /// <summary>
  449. /// 设置数据处理适配器
  450. /// </summary>
  451. /// <param name="adapter"></param>
  452. public virtual void SetDataHandlingAdapter(DataHandlingAdapter adapter)
  453. {
  454. if (!this.CanSetDataHandlingAdapter)
  455. {
  456. throw new Exception($"不允许自由调用{nameof(SetDataHandlingAdapter)}进行赋值。");
  457. }
  458. this.SetAdapter(adapter);
  459. }
  460. /// <summary>
  461. /// <inheritdoc/>
  462. /// </summary>
  463. /// <param name="ipHost"></param>
  464. /// <returns></returns>
  465. public ITcpClient Setup(string ipHost)
  466. {
  467. TouchSocketConfig config = new TouchSocketConfig();
  468. config.SetRemoteIPHost(new IPHost(ipHost));
  469. return this.Setup(config);
  470. }
  471. /// <summary>
  472. /// 配置服务器
  473. /// </summary>
  474. /// <param name="config"></param>
  475. /// <exception cref="Exception"></exception>
  476. public ITcpClient Setup(TouchSocketConfig config)
  477. {
  478. this.Config = config;
  479. this.PluginsManager = config.PluginsManager;
  480. if (config.IsUsePlugin)
  481. {
  482. this.PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadingConfig), this, new ConfigEventArgs(config));
  483. }
  484. this.LoadConfig(this.Config);
  485. if (this.UsePlugin)
  486. {
  487. this.PluginsManager.Raise<IConfigPlugin>(nameof(IConfigPlugin.OnLoadedConfig), this, new ConfigEventArgs(config));
  488. }
  489. return this;
  490. }
  491. private void PrivateHandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
  492. {
  493. if (this.OnHandleReceivedData?.Invoke(byteBlock, requestInfo) == false)
  494. {
  495. return;
  496. }
  497. if (this.UsePlugin)
  498. {
  499. ReceivedDataEventArgs args = new ReceivedDataEventArgs(byteBlock, requestInfo);
  500. this.PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnReceivedData), this, args);
  501. if (args.Handled)
  502. {
  503. return;
  504. }
  505. }
  506. this.HandleReceivedData(byteBlock, requestInfo);
  507. }
  508. /// <summary>
  509. /// 处理已接收到的数据。
  510. /// </summary>
  511. /// <param name="byteBlock">以二进制流形式传递</param>
  512. /// <param name="requestInfo">以解析的数据对象传递</param>
  513. protected virtual void HandleReceivedData(ByteBlock byteBlock, IRequestInfo requestInfo)
  514. {
  515. }
  516. /// <summary>
  517. /// 当即将发送时,如果覆盖父类方法,则不会触发插件。
  518. /// </summary>
  519. /// <param name="buffer">数据缓存区</param>
  520. /// <param name="offset">偏移</param>
  521. /// <param name="length">长度</param>
  522. /// <returns>返回值表示是否允许发送</returns>
  523. protected virtual bool HandleSendingData(byte[] buffer, int offset, int length)
  524. {
  525. if (this.UsePlugin)
  526. {
  527. SendingEventArgs args = new SendingEventArgs(buffer, offset, length);
  528. this.PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnSendingData), this, args);
  529. if (args.IsPermitOperation)
  530. {
  531. return true;
  532. }
  533. return false;
  534. }
  535. return true;
  536. }
  537. /// <summary>
  538. /// 加载配置
  539. /// </summary>
  540. /// <param name="config"></param>
  541. protected virtual void LoadConfig(TouchSocketConfig config)
  542. {
  543. if (config == null)
  544. {
  545. throw new Exception("配置文件为空");
  546. }
  547. this.RemoteIPHost = config.GetValue(TouchSocketConfigExtension.RemoteIPHostProperty);
  548. this.BufferLength = config.GetValue(TouchSocketConfigExtension.BufferLengthProperty);
  549. this.ReceiveType = config.GetValue(TouchSocketConfigExtension.ReceiveTypeProperty);
  550. this.UsePlugin = config.IsUsePlugin;
  551. this.Logger = this.Container.Resolve<ILog>();
  552. if (config.GetValue(TouchSocketConfigExtension.SslOptionProperty) != null)
  553. {
  554. this.UseSsl = true;
  555. }
  556. }
  557. /// <summary>
  558. /// 在延迟发生错误
  559. /// </summary>
  560. /// <param name="ex"></param>
  561. protected virtual void OnDelaySenderError(Exception ex)
  562. {
  563. this.Logger.Log(LogType.Error, this, "发送错误", ex);
  564. }
  565. /// <summary>
  566. /// 设置适配器,该方法不会检验<see cref="CanSetDataHandlingAdapter"/>的值。
  567. /// </summary>
  568. /// <param name="adapter"></param>
  569. protected void SetAdapter(DataHandlingAdapter adapter)
  570. {
  571. if (adapter is null)
  572. {
  573. throw new ArgumentNullException(nameof(adapter));
  574. }
  575. if (this.Config != null)
  576. {
  577. if (this.Config.GetValue(TouchSocketConfigExtension.MaxPackageSizeProperty) is int v1)
  578. {
  579. adapter.MaxPackageSize = v1;
  580. }
  581. if (this.Config.GetValue(TouchSocketConfigExtension.CacheTimeoutProperty) != TimeSpan.Zero)
  582. {
  583. adapter.CacheTimeout = this.Config.GetValue(TouchSocketConfigExtension.CacheTimeoutProperty);
  584. }
  585. if (this.Config.GetValue(TouchSocketConfigExtension.CacheTimeoutEnableProperty) is bool v2)
  586. {
  587. adapter.CacheTimeoutEnable = v2;
  588. }
  589. if (this.Config.GetValue(TouchSocketConfigExtension.UpdateCacheTimeWhenRevProperty) is bool v3)
  590. {
  591. adapter.UpdateCacheTimeWhenRev = v3;
  592. }
  593. }
  594. adapter.OnLoaded(this);
  595. adapter.ReceivedCallBack = this.PrivateHandleReceivedData;
  596. adapter.SendCallBack = this.DefaultSend;
  597. this.DataHandlingAdapter = adapter;
  598. }
  599. private void BeginReceive()
  600. {
  601. this.m_workStream.SafeDispose();
  602. if (this.UseSsl)
  603. {
  604. ClientSslOption sslOption = (ClientSslOption)this.Config.GetValue(TouchSocketConfigExtension.SslOptionProperty);
  605. SslStream sslStream = (sslOption.CertificateValidationCallback != null) ? new SslStream(new NetworkStream(this.MainSocket, false), false, sslOption.CertificateValidationCallback) : new SslStream(new NetworkStream(this.MainSocket, false), false);
  606. if (sslOption.ClientCertificates == null)
  607. {
  608. sslStream.AuthenticateAsClient(sslOption.TargetHost);
  609. }
  610. else
  611. {
  612. sslStream.AuthenticateAsClient(sslOption.TargetHost, sslOption.ClientCertificates, sslOption.SslProtocols, sslOption.CheckCertificateRevocation);
  613. }
  614. this.m_workStream = sslStream;
  615. if (this.ReceiveType != ReceiveType.None)
  616. {
  617. this.BeginSsl();
  618. }
  619. }
  620. else
  621. {
  622. if (this.ReceiveType == ReceiveType.Auto)
  623. {
  624. SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
  625. eventArgs.Completed += this.EventArgs_Completed;
  626. ByteBlock byteBlock = BytePool.Default.GetByteBlock(this.BufferLength);
  627. eventArgs.UserToken = byteBlock;
  628. eventArgs.SetBuffer(byteBlock.Buffer, 0, byteBlock.Buffer.Length);
  629. if (!this.MainSocket.ReceiveAsync(eventArgs))
  630. {
  631. this.ProcessReceived(eventArgs);
  632. }
  633. }
  634. }
  635. }
  636. private void BeginSsl()
  637. {
  638. ByteBlock byteBlock = new ByteBlock(this.BufferLength);
  639. try
  640. {
  641. this.m_workStream.BeginRead(byteBlock.Buffer, 0, byteBlock.Capacity, this.EndSsl, byteBlock);
  642. }
  643. catch (Exception ex)
  644. {
  645. byteBlock.Dispose();
  646. this.BreakOut(ex.Message, false);
  647. }
  648. }
  649. private void EndSsl(IAsyncResult result)
  650. {
  651. ByteBlock byteBlock = (ByteBlock)result.AsyncState;
  652. try
  653. {
  654. int r = this.m_workStream.EndRead(result);
  655. if (r == 0)
  656. {
  657. this.BreakOut("远程终端主动关闭", false);
  658. }
  659. byteBlock.SetLength(r);
  660. this.HandleBuffer(byteBlock);
  661. this.BeginSsl();
  662. }
  663. catch (System.Exception ex)
  664. {
  665. byteBlock.Dispose();
  666. this.BreakOut(ex.Message, false);
  667. }
  668. }
  669. private Socket CreateSocket(IPHost iPHost)
  670. {
  671. Socket socket = new Socket(iPHost.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
  672. socket.ReceiveBufferSize = this.BufferLength;
  673. socket.SendBufferSize = this.BufferLength;
  674. #if NET45_OR_GREATER
  675. KeepAliveValue keepAliveValue = this.Config.GetValue<KeepAliveValue>(TouchSocketConfigExtension.KeepAliveValueProperty);
  676. if (keepAliveValue.Enable)
  677. {
  678. socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
  679. socket.IOControl(IOControlCode.KeepAliveValues, keepAliveValue.KeepAliveTime, null);
  680. }
  681. #else
  682. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  683. {
  684. KeepAliveValue keepAliveValue = Config.GetValue<KeepAliveValue>(TouchSocketConfigExtension.KeepAliveValueProperty);
  685. if (keepAliveValue.Enable)
  686. {
  687. socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
  688. socket.IOControl(IOControlCode.KeepAliveValues, keepAliveValue.KeepAliveTime, null);
  689. }
  690. }
  691. #endif
  692. socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, this.Config.GetValue<bool>(TouchSocketConfigExtension.NoDelayProperty));
  693. if (this.Config.GetValue<IPHost>(TouchSocketConfigExtension.BindIPHostProperty) != null)
  694. {
  695. if (this.Config.GetValue<bool>(TouchSocketConfigExtension.ReuseAddressProperty))
  696. {
  697. socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  698. }
  699. socket.Bind(this.Config.GetValue<IPHost>(TouchSocketConfigExtension.BindIPHostProperty).EndPoint);
  700. }
  701. return socket;
  702. }
  703. private void EventArgs_Completed(object sender, SocketAsyncEventArgs e)
  704. {
  705. try
  706. {
  707. this.ProcessReceived(e);
  708. }
  709. catch (System.Exception ex)
  710. {
  711. e.Dispose();
  712. this.BreakOut(ex.Message, false);
  713. }
  714. }
  715. /// <summary>
  716. /// 处理数据
  717. /// </summary>
  718. private void HandleBuffer(ByteBlock byteBlock)
  719. {
  720. try
  721. {
  722. this.LastReceivedTime = DateTime.Now;
  723. if (this.OnHandleRawBuffer?.Invoke(byteBlock) == false)
  724. {
  725. return;
  726. }
  727. if (this.DisposedValue)
  728. {
  729. return;
  730. }
  731. if (this.UsePlugin && this.PluginsManager.Raise<ITcpPlugin>(nameof(ITcpPlugin.OnReceivingData), this, new ByteBlockEventArgs(byteBlock)))
  732. {
  733. return;
  734. }
  735. if (this.DataHandlingAdapter == null)
  736. {
  737. this.Logger.Error(this, TouchSocketStatus.NullDataAdapter.GetDescription());
  738. return;
  739. }
  740. this.DataHandlingAdapter.ReceivedInput(byteBlock);
  741. }
  742. catch (Exception ex)
  743. {
  744. this.Logger.Log(LogType.Error, this, "在处理数据时发生错误", ex);
  745. }
  746. finally
  747. {
  748. byteBlock.Dispose();
  749. }
  750. }
  751. #region 发送
  752. #region 同步发送
  753. /// <summary>
  754. /// <inheritdoc/>
  755. /// </summary>
  756. /// <param name="requestInfo"></param>
  757. /// <exception cref="NotConnectedException"></exception>
  758. /// <exception cref="OverlengthException"></exception>
  759. /// <exception cref="Exception"></exception>
  760. public void Send(IRequestInfo requestInfo)
  761. {
  762. if (this.DisposedValue)
  763. {
  764. return;
  765. }
  766. if (this.DataHandlingAdapter == null)
  767. {
  768. throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
  769. }
  770. if (!this.DataHandlingAdapter.CanSendRequestInfo)
  771. {
  772. throw new NotSupportedException($"当前适配器不支持对象发送。");
  773. }
  774. this.DataHandlingAdapter.SendInput(requestInfo);
  775. }
  776. /// <summary>
  777. /// <inheritdoc/>
  778. /// </summary>
  779. /// <param name="buffer"><inheritdoc/></param>
  780. /// <param name="offset"><inheritdoc/></param>
  781. /// <param name="length"><inheritdoc/></param>
  782. /// <exception cref="NotConnectedException"><inheritdoc/></exception>
  783. /// <exception cref="OverlengthException"><inheritdoc/></exception>
  784. /// <exception cref="Exception"><inheritdoc/></exception>
  785. public virtual void Send(byte[] buffer, int offset, int length)
  786. {
  787. if (this.DataHandlingAdapter == null)
  788. {
  789. throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
  790. }
  791. this.DataHandlingAdapter.SendInput(buffer, offset, length);
  792. }
  793. /// <summary>
  794. /// <inheritdoc/>
  795. /// </summary>
  796. /// <param name="transferBytes"><inheritdoc/></param>
  797. /// <exception cref="NotConnectedException"><inheritdoc/></exception>
  798. /// <exception cref="OverlengthException"><inheritdoc/></exception>
  799. /// <exception cref="Exception"><inheritdoc/></exception>
  800. public virtual void Send(IList<ArraySegment<byte>> transferBytes)
  801. {
  802. if (this.DataHandlingAdapter == null)
  803. {
  804. throw new ArgumentNullException(nameof(this.DataHandlingAdapter), TouchSocketStatus.NullDataAdapter.GetDescription());
  805. }
  806. if (this.DataHandlingAdapter.CanSplicingSend)
  807. {
  808. this.DataHandlingAdapter.SendInput(transferBytes);
  809. }
  810. else
  811. {
  812. ByteBlock byteBlock = BytePool.Default.GetByteBlock(this.BufferLength);
  813. try
  814. {
  815. foreach (var item in transferBytes)
  816. {
  817. byteBlock.Write(item.Array, item.Offset, item.Count);
  818. }
  819. this.DataHandlingAdapter.SendInput(byteBlock.Buffer, 0, byteBlock.Len);
  820. }
  821. finally
  822. {
  823. byteBlock.Dispose();
  824. }
  825. }
  826. }
  827. #endregion 同步发送
  828. #region 异步发送
  829. /// <summary>
  830. /// <inheritdoc/>
  831. /// </summary>
  832. /// <param name="buffer"><inheritdoc/></param>
  833. /// <param name="offset"><inheritdoc/></param>
  834. /// <param name="length"><inheritdoc/></param>
  835. /// <exception cref="NotConnectedException"><inheritdoc/></exception>
  836. /// <exception cref="OverlengthException"><inheritdoc/></exception>
  837. /// <exception cref="Exception"><inheritdoc/></exception>
  838. public virtual Task SendAsync(byte[] buffer, int offset, int length)
  839. {
  840. return EasyTask.Run(() =>
  841. {
  842. this.Send(buffer, offset, length);
  843. });
  844. }
  845. /// <summary>
  846. /// <inheritdoc/>
  847. /// </summary>
  848. /// <param name="requestInfo"></param>
  849. /// <exception cref="NotConnectedException"></exception>
  850. /// <exception cref="OverlengthException"></exception>
  851. /// <exception cref="Exception"></exception>
  852. public virtual Task SendAsync(IRequestInfo requestInfo)
  853. {
  854. return EasyTask.Run(() =>
  855. {
  856. this.Send(requestInfo);
  857. });
  858. }
  859. /// <summary>
  860. /// <inheritdoc/>
  861. /// </summary>
  862. /// <param name="transferBytes"><inheritdoc/></param>
  863. /// <exception cref="NotConnectedException"><inheritdoc/></exception>
  864. /// <exception cref="OverlengthException"><inheritdoc/></exception>
  865. /// <exception cref="Exception"><inheritdoc/></exception>
  866. public virtual Task SendAsync(IList<ArraySegment<byte>> transferBytes)
  867. {
  868. return EasyTask.Run(() =>
  869. {
  870. this.Send(transferBytes);
  871. });
  872. }
  873. #endregion 异步发送
  874. /// <summary>
  875. /// <inheritdoc/>
  876. /// </summary>
  877. /// <param name="buffer"><inheritdoc/></param>
  878. /// <param name="offset"><inheritdoc/></param>
  879. /// <param name="length"><inheritdoc/></param>
  880. /// <exception cref="NotConnectedException"><inheritdoc/></exception>
  881. /// <exception cref="OverlengthException"><inheritdoc/></exception>
  882. /// <exception cref="Exception"><inheritdoc/></exception>
  883. public void DefaultSend(byte[] buffer, int offset, int length)
  884. {
  885. if (!this.CanSend)
  886. {
  887. throw new NotConnectedException(TouchSocketStatus.NotConnected.GetDescription());
  888. }
  889. if (this.HandleSendingData(buffer, offset, length))
  890. {
  891. if (this.UseSsl)
  892. {
  893. this.m_workStream.Write(buffer, offset, length);
  894. }
  895. else
  896. {
  897. if (this.m_useDelaySender && length < TouchSocketUtility.BigDataBoundary)
  898. {
  899. this.m_delaySender.Send(new QueueDataBytes(buffer, offset, length));
  900. }
  901. else
  902. {
  903. this.MainSocket.AbsoluteSend(buffer, offset, length);
  904. }
  905. }
  906. this.LastSendTime = DateTime.Now;
  907. }
  908. }
  909. /// <summary>
  910. /// <inheritdoc/>
  911. /// </summary>
  912. /// <param name="buffer"><inheritdoc/></param>
  913. /// <param name="offset"><inheritdoc/></param>
  914. /// <param name="length"><inheritdoc/></param>
  915. /// <exception cref="NotConnectedException"><inheritdoc/></exception>
  916. /// <exception cref="OverlengthException"><inheritdoc/></exception>
  917. /// <exception cref="Exception"><inheritdoc/></exception>
  918. public Task DefaultSendAsync(byte[] buffer, int offset, int length)
  919. {
  920. return EasyTask.Run(() =>
  921. {
  922. this.DefaultSend(buffer, offset, length);
  923. });
  924. }
  925. #endregion 发送
  926. private void LoadSocketAndReadIpPort()
  927. {
  928. if (this.MainSocket == null)
  929. {
  930. this.IP = null;
  931. this.Port = -1;
  932. return;
  933. }
  934. string ipport;
  935. if (this.MainSocket.Connected && this.MainSocket.RemoteEndPoint != null)
  936. {
  937. ipport = this.MainSocket.RemoteEndPoint.ToString();
  938. }
  939. else if (this.MainSocket.IsBound && this.MainSocket.LocalEndPoint != null)
  940. {
  941. ipport = this.MainSocket.LocalEndPoint.ToString();
  942. }
  943. else
  944. {
  945. return;
  946. }
  947. int r = ipport.LastIndexOf(":");
  948. this.IP = ipport.Substring(0, r);
  949. this.Port = Convert.ToInt32(ipport.Substring(r + 1, ipport.Length - (r + 1)));
  950. }
  951. private void ProcessReceived(SocketAsyncEventArgs e)
  952. {
  953. if (!this.CanSend)
  954. {
  955. e.Dispose();
  956. return;
  957. }
  958. if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
  959. {
  960. ByteBlock byteBlock = (ByteBlock)e.UserToken;
  961. byteBlock.SetLength(e.BytesTransferred);
  962. this.HandleBuffer(byteBlock);
  963. try
  964. {
  965. ByteBlock newByteBlock = BytePool.Default.GetByteBlock(this.BufferLength);
  966. e.UserToken = newByteBlock;
  967. e.SetBuffer(newByteBlock.Buffer, 0, newByteBlock.Buffer.Length);
  968. if (!this.MainSocket.ReceiveAsync(e))
  969. {
  970. this.ProcessReceived(e);
  971. }
  972. }
  973. catch (System.Exception ex)
  974. {
  975. e.Dispose();
  976. this.BreakOut(ex.Message, false);
  977. }
  978. }
  979. else
  980. {
  981. e.Dispose();
  982. this.BreakOut("远程终端主动关闭", false);
  983. }
  984. }
  985. }
  986. }