UdpClient.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using System.Text;
  5. namespace HPSocketCS
  6. {
  7. public class UdpClient : ConnectionExtra, IClient
  8. {
  9. /// <summary>
  10. /// 准备连接了事件
  11. /// </summary>
  12. public event ClientEvent.OnPrepareConnectEventHandler OnPrepareConnect;
  13. /// <summary>
  14. /// 连接事件
  15. /// </summary>
  16. public event ClientEvent.OnConnectEventHandler OnConnect;
  17. /// <summary>
  18. /// 数据发送事件
  19. /// </summary>
  20. public event ClientEvent.OnSendEventHandler OnSend;
  21. /// <summary>
  22. /// 数据到达事件
  23. /// </summary>
  24. public event ClientEvent.OnReceiveEventHandler OnReceive;
  25. /// <summary>
  26. /// 数据到达事件(指针数据)
  27. /// </summary>
  28. public event ClientEvent.OnPointerDataReceiveEventHandler OnPointerDataReceive;
  29. /// <summary>
  30. /// 连接关闭事件
  31. /// </summary>
  32. public event ClientEvent.OnCloseEventHandler OnClose;
  33. /// <summary>
  34. /// 握手事件
  35. /// </summary>
  36. public event ClientEvent.OnHandShakeEventHandler OnHandShake;
  37. protected IntPtr pClient = IntPtr.Zero;
  38. protected IntPtr pListener = IntPtr.Zero;
  39. protected bool IsCreate = false;
  40. ConnectionExtra ExtraData = new ConnectionExtra();
  41. public UdpClient()
  42. {
  43. CreateListener();
  44. }
  45. ~UdpClient()
  46. {
  47. Destroy();
  48. }
  49. /// <summary>
  50. /// 创建socket监听&服务组件
  51. /// </summary>
  52. /// <returns></returns>
  53. protected virtual bool CreateListener()
  54. {
  55. if (IsCreate == true || pListener != IntPtr.Zero || pClient != IntPtr.Zero)
  56. {
  57. return false;
  58. }
  59. pListener = Sdk.Create_HP_UdpClientListener();
  60. if (pListener == IntPtr.Zero)
  61. {
  62. return false;
  63. }
  64. pClient = Sdk.Create_HP_UdpClient(pListener);
  65. if (pClient == IntPtr.Zero)
  66. {
  67. return false;
  68. }
  69. IsCreate = true;
  70. return true;
  71. }
  72. /// <summary>
  73. /// 终止服务并释放资源
  74. /// </summary>
  75. public virtual void Destroy()
  76. {
  77. Stop();
  78. if (pClient != IntPtr.Zero)
  79. {
  80. Sdk.Destroy_HP_UdpClient(pClient);
  81. pClient = IntPtr.Zero;
  82. }
  83. if (pListener != IntPtr.Zero)
  84. {
  85. Sdk.Destroy_HP_UdpClientListener(pListener);
  86. pListener = IntPtr.Zero;
  87. }
  88. IsCreate = false;
  89. }
  90. /// <summary>
  91. /// 启动通讯组件并连接到服务器
  92. /// </summary>
  93. /// <param name="address">远程地址</param>
  94. /// <param name="port">远程端口</param>
  95. /// <param name="async">是否异步</param>
  96. /// <returns></returns>
  97. public bool Connect(string address, ushort port, bool async = true)
  98. {
  99. if (string.IsNullOrEmpty(address) == true)
  100. {
  101. throw new Exception("address is null");
  102. }
  103. else if (port == 0)
  104. {
  105. throw new Exception("port is zero");
  106. }
  107. if (pClient == IntPtr.Zero)
  108. {
  109. return false;
  110. }
  111. this.SetCallback();
  112. return Sdk.HP_Client_Start(pClient, address, port, async);
  113. }
  114. /// <summary>
  115. /// 启动通讯组件并连接到服务器
  116. /// </summary>
  117. /// <param name="address">远程地址</param>
  118. /// <param name="port">远程端口</param>
  119. /// <param name="bindAddress">本地绑定到哪个ip?,多ip下可以选择绑定到指定ip</param>
  120. /// <param name="async">是否异步</param>
  121. /// <returns></returns>
  122. public bool Connect(string address, ushort port, string bindAddress, bool async = true)
  123. {
  124. if (string.IsNullOrEmpty(address) == true)
  125. {
  126. throw new Exception("address is null");
  127. }
  128. else if (port == 0)
  129. {
  130. throw new Exception("port is zero");
  131. }
  132. if (pClient == IntPtr.Zero)
  133. {
  134. return false;
  135. }
  136. this.SetCallback();
  137. return Sdk.HP_Client_StartWithBindAddress(pClient, address, port, async, bindAddress);
  138. }
  139. /// <summary>
  140. /// 启动通讯组件并连接到服务器
  141. /// </summary>
  142. /// <param name="address">远程地址</param>
  143. /// <param name="port">远程端口</param>
  144. /// <param name="bindAddress">本地绑定到哪个ip?,多ip下可以选择绑定到指定ip</param>
  145. /// <param name="usLocalPort">本地端口</param>
  146. /// <param name="async">是否异步</param>
  147. /// <returns></returns>
  148. public bool Connect(string address, ushort port, string bindAddress, ushort usLocalPort, bool async = true)
  149. {
  150. if (string.IsNullOrEmpty(address) == true)
  151. {
  152. throw new Exception("address is null");
  153. }
  154. else if (port == 0)
  155. {
  156. throw new Exception("port is zero");
  157. }
  158. if (pClient == IntPtr.Zero)
  159. {
  160. return false;
  161. }
  162. this.SetCallback();
  163. return Sdk.HP_Client_StartWithBindAddressAndLocalPort(pClient, address, port, async, bindAddress, usLocalPort);
  164. }
  165. /// <summary>
  166. /// 停止通讯组件
  167. /// </summary>
  168. /// <returns></returns>
  169. public bool Stop()
  170. {
  171. if (pClient == IntPtr.Zero)
  172. {
  173. return false;
  174. }
  175. return Sdk.HP_Client_Stop(pClient);
  176. }
  177. /// <summary>
  178. /// 发送数据
  179. /// </summary>
  180. /// <param name="bytes"></param>
  181. /// <param name="size"></param>
  182. /// <returns></returns>
  183. public bool Send(byte[] bytes, int size)
  184. {
  185. return Sdk.HP_Client_Send(pClient, bytes, size);
  186. }
  187. /// <summary>
  188. /// 发送数据
  189. /// </summary>
  190. /// <param name="bufferPtr"></param>
  191. /// <param name="size"></param>
  192. /// <returns></returns>
  193. public bool Send(IntPtr bufferPtr, int size)
  194. {
  195. return Sdk.HP_Client_Send(pClient, bufferPtr, size);
  196. }
  197. /// <summary>
  198. /// 发送数据
  199. /// </summary>
  200. /// <param name="bytes"></param>
  201. /// <param name="offset">针对bytes的偏移</param>
  202. /// <param name="size">发多大</param>
  203. /// <returns></returns>
  204. public bool Send(byte[] bytes, int offset, int size)
  205. {
  206. return Sdk.HP_Client_SendPart(pClient, bytes, size, offset);
  207. }
  208. /// <summary>
  209. /// 发送数据
  210. /// </summary>
  211. /// <param name="bufferPtr"></param>
  212. /// <param name="offset">针对bufferPtr的偏移</param>
  213. /// <param name="size">发多大</param>
  214. /// <returns></returns>
  215. public bool Send(IntPtr bufferPtr, int offset, int size)
  216. {
  217. return Sdk.HP_Client_SendPart(pClient, bufferPtr, size, offset);
  218. }
  219. /// <summary>
  220. /// 发送多组数据
  221. /// 向指定连接发送多组数据
  222. /// TCP - 顺序发送所有数据包
  223. /// </summary>
  224. /// <param name="buffers">发送缓冲区数组</param>
  225. /// <param name="count">发送缓冲区数目</param>
  226. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  227. public bool SendPackets(WSABUF[] buffers, int count)
  228. {
  229. return Sdk.HP_Client_SendPackets(pClient, buffers, count);
  230. }
  231. /// <summary>
  232. /// 发送多组数据
  233. /// 向指定连接发送多组数据
  234. /// TCP - 顺序发送所有数据包
  235. /// </summary>
  236. /// <param name="objects">发送缓冲区数组</param>
  237. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  238. public bool SendPackets<T>(T[] objects)
  239. {
  240. bool ret = false;
  241. WSABUF[] buffer = new WSABUF[objects.Length];
  242. IntPtr[] ptrs = new IntPtr[buffer.Length];
  243. try
  244. {
  245. for (int i = 0; i < objects.Length; i++)
  246. {
  247. buffer[i].Length = Marshal.SizeOf(typeof(T));
  248. ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length);
  249. Marshal.StructureToPtr(objects[i], ptrs[i], true);
  250. buffer[i].Buffer = ptrs[i];
  251. }
  252. ret = SendPackets(buffer, buffer.Length);
  253. }
  254. catch (Exception ex)
  255. {
  256. throw ex;
  257. }
  258. finally
  259. {
  260. foreach (var ptr in ptrs)
  261. {
  262. if (ptr != IntPtr.Zero)
  263. {
  264. Marshal.FreeHGlobal(ptr);
  265. }
  266. }
  267. }
  268. return ret;
  269. }
  270. /// <summary>
  271. /// 获取错误码
  272. /// </summary>
  273. public SocketError ErrorCode
  274. {
  275. get
  276. {
  277. return Sdk.HP_Client_GetLastError(pClient);
  278. }
  279. }
  280. /// <summary>
  281. /// 版本号
  282. /// </summary>
  283. public string Version
  284. {
  285. get
  286. {
  287. return Sdk.GetHPSocketVersion();
  288. }
  289. }
  290. /// <summary>
  291. /// 获取错误信息
  292. /// </summary>
  293. public string ErrorMessage
  294. {
  295. get
  296. {
  297. IntPtr ptr = Sdk.HP_Client_GetLastErrorDesc(pClient);
  298. string desc = Marshal.PtrToStringAnsi(ptr);
  299. return desc;
  300. }
  301. }
  302. /// <summary>
  303. /// 获取或设置接收状态
  304. /// </summary>
  305. public ReceiveState ReceiveState
  306. {
  307. get
  308. {
  309. int state = -1;
  310. if (Sdk.HP_Client_IsPauseReceive(pClient, ref state))
  311. {
  312. return (ReceiveState)state;
  313. }
  314. return ReceiveState.Unknown;
  315. }
  316. set
  317. {
  318. Sdk.HP_Client_PauseReceive(pClient, (int)value);
  319. }
  320. }
  321. /// <summary>
  322. /// </summary>
  323. /// <param name="length"></param>
  324. /// <returns></returns>
  325. public bool GetPendingDataLength(ref int length)
  326. {
  327. return Sdk.HP_Client_GetPendingDataLength(pClient, ref length);
  328. }
  329. /// <summary>
  330. /// 获取附加数据
  331. /// </summary>
  332. /// <returns></returns>
  333. public T GetExtra<T>()
  334. {
  335. return (T)ExtraData.GetExtra(pClient);
  336. }
  337. /// <summary>
  338. /// 设置附加数据
  339. ///
  340. /// </summary>
  341. /// <param name="newValue"></param>
  342. /// <returns></returns>
  343. public bool SetExtra(object newValue)
  344. {
  345. return ExtraData.SetExtra(pClient, newValue);
  346. }
  347. /// <summary>
  348. /// 删除附加数据
  349. /// </summary>
  350. /// <param name="key"></param>
  351. /// <returns></returns>
  352. public bool RemoveExtra()
  353. {
  354. return ExtraData.RemoveExtra(pClient);
  355. }
  356. /// <summary>
  357. /// 获取监听socket的地址信息
  358. /// </summary>
  359. /// <param name="ip"></param>
  360. /// <param name="port"></param>
  361. /// <returns></returns>
  362. public bool GetListenAddress(ref string ip, ref ushort port)
  363. {
  364. int ipLength = 40;
  365. StringBuilder sb = new StringBuilder(ipLength);
  366. bool ret = Sdk.HP_Client_GetLocalAddress(pClient, sb, ref ipLength, ref port);
  367. if (ret == true)
  368. {
  369. ip = sb.ToString();
  370. }
  371. return ret;
  372. }
  373. /// <summary>
  374. /// 获取连接的远程主机信息
  375. /// </summary>
  376. /// <param name="host"></param>
  377. /// <param name="port"></param>
  378. /// <returns></returns>
  379. public bool GetRemoteHost(ref string host, ref ushort port)
  380. {
  381. int ipLength = 40;
  382. StringBuilder sb = new StringBuilder(ipLength);
  383. bool ret = Sdk.HP_Client_GetRemoteHost(pClient, sb, ref ipLength, ref port);
  384. if (ret == true)
  385. {
  386. host = sb.ToString();
  387. }
  388. return ret;
  389. }
  390. /// <summary>
  391. /// 是否启动
  392. /// </summary>
  393. public bool IsStarted
  394. {
  395. get
  396. {
  397. if (pClient == IntPtr.Zero)
  398. {
  399. return false;
  400. }
  401. return Sdk.HP_Client_HasStarted(pClient);
  402. }
  403. }
  404. /// <summary>
  405. /// 状态
  406. /// </summary>
  407. public ServiceState State
  408. {
  409. get
  410. {
  411. return Sdk.HP_Client_GetState(pClient);
  412. }
  413. }
  414. /// <summary>
  415. /// 获取该组件对象的连接Id
  416. /// </summary>
  417. public IntPtr ConnectionId
  418. {
  419. get
  420. {
  421. return Sdk.HP_Client_GetConnectionID(pClient);
  422. }
  423. }
  424. /// <summary>
  425. /// 检测是否为安全连接(SSL/HTTPS)
  426. /// </summary>
  427. public bool IsSecure
  428. {
  429. get
  430. {
  431. return Sdk.HP_Client_IsSecure(pClient);
  432. }
  433. }
  434. ///////////////////////////////////////////////////////////////////////////////////////
  435. /// <summary>
  436. /// 读取或设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 )
  437. /// </summary>
  438. public uint FreeBufferPoolSize
  439. {
  440. get
  441. {
  442. return Sdk.HP_Client_GetFreeBufferPoolSize(pClient);
  443. }
  444. set
  445. {
  446. Sdk.HP_Client_SetFreeBufferPoolSize(pClient, value);
  447. }
  448. }
  449. /// <summary>
  450. /// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍)
  451. /// </summary>
  452. public uint FreeBufferPoolHold
  453. {
  454. get
  455. {
  456. return Sdk.HP_Client_GetFreeBufferPoolHold(pClient);
  457. }
  458. set
  459. {
  460. Sdk.HP_Client_SetFreeBufferPoolHold(pClient, value);
  461. }
  462. }
  463. ///////////////////////////////////////////////////////////////////////////////////////
  464. /// <summary>
  465. /// 根据错误码返回错误信息
  466. /// </summary>
  467. /// <param name="code"></param>
  468. /// <returns></returns>
  469. public string GetSocketErrorDesc(SocketError code)
  470. {
  471. IntPtr ptr = Sdk.HP_GetSocketErrorDesc(code);
  472. string desc = Marshal.PtrToStringAnsi(ptr);
  473. return desc;
  474. }
  475. ///////////////////////////////////////////////////////////////////////////////////////
  476. protected Sdk.OnPrepareConnect _OnPrepareConnect = null;
  477. protected Sdk.OnConnect _OnConnect = null;
  478. protected Sdk.OnReceive _OnReceive = null;
  479. protected Sdk.OnSend _OnSend = null;
  480. protected Sdk.OnClose _OnClose = null;
  481. protected Sdk.OnHandShake _OnHandShake = null;
  482. /// <summary>
  483. /// 设置回调函数
  484. /// </summary>
  485. protected virtual void SetCallback()
  486. {
  487. // 设置 Socket 监听器回调函数
  488. _OnPrepareConnect = new Sdk.OnPrepareConnect(SDK_OnPrepareConnect);
  489. _OnConnect = new Sdk.OnConnect(SDK_OnConnect);
  490. _OnSend = new Sdk.OnSend(SDK_OnSend);
  491. _OnReceive = new Sdk.OnReceive(SDK_OnReceive);
  492. _OnClose = new Sdk.OnClose(SDK_OnClose);
  493. _OnHandShake = new Sdk.OnHandShake(SDK_OnHandShake);
  494. Sdk.HP_Set_FN_Client_OnPrepareConnect(pListener, _OnPrepareConnect);
  495. Sdk.HP_Set_FN_Client_OnConnect(pListener, _OnConnect);
  496. Sdk.HP_Set_FN_Client_OnSend(pListener, _OnSend);
  497. Sdk.HP_Set_FN_Client_OnReceive(pListener, _OnReceive);
  498. Sdk.HP_Set_FN_Client_OnClose(pListener, _OnClose);
  499. Sdk.HP_Set_FN_Client_OnHandShake(pListener, _OnHandShake);
  500. }
  501. protected HandleResult SDK_OnPrepareConnect(IntPtr pSender, IntPtr connId, IntPtr socket)
  502. {
  503. if (OnPrepareConnect != null)
  504. {
  505. return OnPrepareConnect(this, socket);
  506. }
  507. return HandleResult.Ignore;
  508. }
  509. protected HandleResult SDK_OnConnect(IntPtr pSender, IntPtr connId)
  510. {
  511. if (OnConnect != null)
  512. {
  513. return OnConnect(this);
  514. }
  515. return HandleResult.Ignore;
  516. }
  517. protected HandleResult SDK_OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length)
  518. {
  519. if (OnSend != null)
  520. {
  521. byte[] bytes = new byte[length];
  522. Marshal.Copy(pData, bytes, 0, length);
  523. return OnSend(this, bytes);
  524. }
  525. return HandleResult.Ignore;
  526. }
  527. protected HandleResult SDK_OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length)
  528. {
  529. if (OnPointerDataReceive != null)
  530. {
  531. return OnPointerDataReceive(this, pData, length);
  532. }
  533. else if (OnReceive != null)
  534. {
  535. byte[] bytes = new byte[length];
  536. Marshal.Copy(pData, bytes, 0, length);
  537. return OnReceive(this, bytes);
  538. }
  539. return HandleResult.Ignore;
  540. }
  541. protected HandleResult SDK_OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode)
  542. {
  543. if (OnClose != null)
  544. {
  545. return OnClose(this, enOperation, errorCode);
  546. }
  547. return HandleResult.Ignore;
  548. }
  549. protected HandleResult SDK_OnHandShake(IntPtr pSender, IntPtr connId)
  550. {
  551. if (OnHandShake != null)
  552. {
  553. return OnHandShake(this);
  554. }
  555. return HandleResult.Ignore;
  556. }
  557. ///////////////////////////////////////////////////////////////////////////
  558. /// <summary>
  559. /// 获取系统返回的错误码
  560. /// </summary>
  561. public int SYSGetLastError()
  562. {
  563. return Sdk.SYS_GetLastError();
  564. }
  565. /// <summary>
  566. /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码
  567. /// </summary>
  568. public int SYSWSAGetLastError()
  569. {
  570. return Sdk.SYS_WSAGetLastError();
  571. }
  572. /// <summary>
  573. /// 调用系统的 setsockopt()
  574. /// </summary>
  575. /// <param name="sock"></param>
  576. /// <param name="level"></param>
  577. /// <param name="name"></param>
  578. /// <param name="val"></param>
  579. /// <param name="len"></param>
  580. /// <returns></returns>
  581. public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len)
  582. {
  583. return Sdk.SYS_SetSocketOption(sock, level, name, val, len);
  584. }
  585. /// <summary>
  586. /// 调用系统的 getsockopt()
  587. /// </summary>
  588. /// <param name="sock"></param>
  589. /// <param name="level"></param>
  590. /// <param name="name"></param>
  591. /// <param name="val"></param>
  592. /// <param name="len"></param>
  593. /// <returns></returns>
  594. public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len)
  595. {
  596. return Sdk.SYS_GetSocketOption(sock, level, name, val, ref len);
  597. }
  598. /// <summary>
  599. /// 调用系统的 ioctlsocket()
  600. /// </summary>
  601. /// <param name="sock"></param>
  602. /// <param name="cmd"></param>
  603. /// <param name="arg"></param>
  604. /// <returns></returns>
  605. public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg)
  606. {
  607. return Sdk.SYS_IoctlSocket(sock, cmd, arg);
  608. }
  609. /// <summary>
  610. /// 调用系统的 ::WSAIoctl()
  611. /// </summary>
  612. /// <param name="sock"></param>
  613. /// <param name="dwIoControlCode"></param>
  614. /// <param name="lpvInBuffer"></param>
  615. /// <param name="cbInBuffer"></param>
  616. /// <param name="lpvOutBuffer"></param>
  617. /// <param name="cbOutBuffer"></param>
  618. /// <param name="lpcbBytesReturned"></param>
  619. /// <returns></returns>
  620. public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer,
  621. IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned)
  622. {
  623. return Sdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer,
  624. lpvOutBuffer, cbOutBuffer, lpcbBytesReturned);
  625. }
  626. }
  627. }