TcpClient.cs 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Runtime.Serialization;
  7. using System.Runtime.Serialization.Formatters.Binary;
  8. using System.Text;
  9. namespace HPSocketCS
  10. {
  11. public class TcpClient<T> : TcpClient
  12. {
  13. public T GetExtra()
  14. {
  15. return base.GetExtra<T>();
  16. }
  17. public bool SetExtra(T obj)
  18. {
  19. return base.SetExtra(obj);
  20. }
  21. }
  22. public class TcpClient : IClient
  23. {
  24. protected IntPtr pClient = IntPtr.Zero;
  25. protected IntPtr pListener = IntPtr.Zero;
  26. protected bool IsCreate = false;
  27. ConnectionExtra ExtraData = new ConnectionExtra();
  28. /****************************************************/
  29. /// <summary>
  30. /// 准备连接了事件
  31. /// </summary>
  32. public event ClientEvent.OnPrepareConnectEventHandler OnPrepareConnect;
  33. /// <summary>
  34. /// 连接事件
  35. /// </summary>
  36. public event ClientEvent.OnConnectEventHandler OnConnect;
  37. /// <summary>
  38. /// 数据发送事件
  39. /// </summary>
  40. public event ClientEvent.OnSendEventHandler OnSend;
  41. /// <summary>
  42. /// 数据到达事件
  43. /// </summary>
  44. public event ClientEvent.OnReceiveEventHandler OnReceive;
  45. /// <summary>
  46. /// 数据到达事件(指针数据)
  47. /// </summary>
  48. public event ClientEvent.OnPointerDataReceiveEventHandler OnPointerDataReceive;
  49. /// <summary>
  50. /// 连接关闭事件
  51. /// </summary>
  52. public event ClientEvent.OnCloseEventHandler OnClose;
  53. /// <summary>
  54. /// 握手事件
  55. /// </summary>
  56. public event ClientEvent.OnHandShakeEventHandler OnHandShake;
  57. public TcpClient()
  58. {
  59. CreateListener();
  60. }
  61. ~TcpClient()
  62. {
  63. Destroy();
  64. }
  65. /// <summary>
  66. /// 创建socket监听&服务组件
  67. /// </summary>
  68. /// <returns></returns>
  69. protected virtual bool CreateListener()
  70. {
  71. if (IsCreate == true || pListener != IntPtr.Zero || pClient != IntPtr.Zero)
  72. {
  73. return false;
  74. }
  75. pListener = Sdk.Create_HP_TcpClientListener();
  76. if (pListener == IntPtr.Zero)
  77. {
  78. return false;
  79. }
  80. pClient = Sdk.Create_HP_TcpClient(pListener);
  81. if (pClient == IntPtr.Zero)
  82. {
  83. return false;
  84. }
  85. IsCreate = true;
  86. return true;
  87. }
  88. /// <summary>
  89. /// 终止服务并释放资源
  90. /// </summary>
  91. public virtual void Destroy()
  92. {
  93. Stop();
  94. if (pClient != IntPtr.Zero)
  95. {
  96. Sdk.Destroy_HP_TcpClient(pClient);
  97. pClient = IntPtr.Zero;
  98. }
  99. if (pListener != IntPtr.Zero)
  100. {
  101. Sdk.Destroy_HP_TcpClientListener(pListener);
  102. pListener = IntPtr.Zero;
  103. }
  104. IsCreate = false;
  105. }
  106. /// <summary>
  107. /// 启动通讯组件并连接到服务器
  108. /// </summary>
  109. /// <param name="address">远程地址</param>
  110. /// <param name="port">远程端口</param>
  111. /// <param name="async">是否异步</param>
  112. /// <returns></returns>
  113. public bool Connect(string address, ushort port, bool async = true)
  114. {
  115. if (string.IsNullOrEmpty(address) == true)
  116. {
  117. throw new Exception("address is null");
  118. }
  119. else if (port == 0)
  120. {
  121. throw new Exception("port is zero");
  122. }
  123. if (pClient == IntPtr.Zero)
  124. {
  125. return false;
  126. }
  127. this.SetCallback();
  128. return Sdk.HP_Client_Start(pClient, address, port, async);
  129. }
  130. /// <summary>
  131. /// 启动通讯组件并连接到服务器
  132. /// </summary>
  133. /// <param name="address">远程地址</param>
  134. /// <param name="port">远程端口</param>
  135. /// <param name="bindAddress">本地绑定到哪个ip?,多ip下可以选择绑定到指定ip</param>
  136. /// <param name="async">是否异步</param>
  137. /// <returns></returns>
  138. public bool Connect(string address, ushort port, string bindAddress, bool async = true)
  139. {
  140. if (string.IsNullOrEmpty(address) == true)
  141. {
  142. throw new Exception("address is null");
  143. }
  144. else if (port == 0)
  145. {
  146. throw new Exception("port is zero");
  147. }
  148. if (pClient == IntPtr.Zero)
  149. {
  150. return false;
  151. }
  152. this.SetCallback();
  153. return Sdk.HP_Client_StartWithBindAddress(pClient, address, port, async, bindAddress);
  154. }
  155. /// <summary>
  156. /// 启动通讯组件并连接到服务器
  157. /// </summary>
  158. /// <param name="address">远程地址</param>
  159. /// <param name="port">远程端口</param>
  160. /// <param name="bindAddress">本地绑定到哪个ip?,多ip下可以选择绑定到指定ip</param>
  161. /// <param name="usLocalPort">本地端口</param>
  162. /// <param name="async">是否异步</param>
  163. /// <returns></returns>
  164. public bool Connect(string address, ushort port, string bindAddress, ushort usLocalPort, bool async = true)
  165. {
  166. if (string.IsNullOrEmpty(address) == true)
  167. {
  168. throw new Exception("address is null");
  169. }
  170. else if (port == 0)
  171. {
  172. throw new Exception("port is zero");
  173. }
  174. if (pClient == IntPtr.Zero)
  175. {
  176. return false;
  177. }
  178. this.SetCallback();
  179. return Sdk.HP_Client_StartWithBindAddressAndLocalPort(pClient, address, port, async, bindAddress, usLocalPort);
  180. }
  181. /// <summary>
  182. /// 停止通讯组件
  183. /// </summary>
  184. /// <returns></returns>
  185. public bool Stop()
  186. {
  187. if (pClient == IntPtr.Zero)
  188. {
  189. return false;
  190. }
  191. return Sdk.HP_Client_Stop(pClient);
  192. }
  193. /// <summary>
  194. /// 发送数据
  195. /// </summary>
  196. /// <param name="bytes"></param>
  197. /// <param name="size"></param>
  198. /// <returns></returns>
  199. public bool Send(byte[] bytes, int size)
  200. {
  201. return Sdk.HP_Client_Send(pClient, bytes, size);
  202. }
  203. /// <summary>
  204. /// 发送数据
  205. /// </summary>
  206. /// <param name="bufferPtr"></param>
  207. /// <param name="size"></param>
  208. /// <returns></returns>
  209. public bool Send(IntPtr bufferPtr, int size)
  210. {
  211. return Sdk.HP_Client_Send(pClient, bufferPtr, size);
  212. }
  213. /// <summary>
  214. /// 发送数据
  215. /// </summary>
  216. /// <param name="bufferPtr"></param>
  217. /// <param name="size"></param>
  218. /// <returns></returns>
  219. public bool Send<T>(T obj)
  220. {
  221. byte[] buffer = StructureToByte<T>(obj);
  222. return Send(buffer, buffer.Length);
  223. }
  224. /// <summary>
  225. /// 序列化对象后发送数据,序列化对象所属类必须标记[Serializable]
  226. /// </summary>
  227. /// <param name="bufferPtr"></param>
  228. /// <param name="size"></param>
  229. /// <returns></returns>
  230. public bool SendBySerializable(object obj)
  231. {
  232. byte[] buffer = ObjectToBytes(obj);
  233. return Send(buffer, buffer.Length);
  234. }
  235. /// <summary>
  236. /// 发送数据
  237. /// </summary>
  238. /// <param name="bytes"></param>
  239. /// <param name="offset">针对bytes的偏移</param>
  240. /// <param name="size">发多大</param>
  241. /// <returns></returns>
  242. public bool Send(byte[] bytes, int offset, int size)
  243. {
  244. return Sdk.HP_Client_SendPart(pClient, bytes, size, offset);
  245. }
  246. /// <summary>
  247. /// 发送数据
  248. /// </summary>
  249. /// <param name="bufferPtr"></param>
  250. /// <param name="offset">针对bufferPtr的偏移</param>
  251. /// <param name="size">发多大</param>
  252. /// <returns></returns>
  253. public bool Send(IntPtr bufferPtr, int offset, int size)
  254. {
  255. return Sdk.HP_Client_SendPart(pClient, bufferPtr, size, offset);
  256. }
  257. /// <summary>
  258. /// 发送多组数据
  259. /// 向指定连接发送多组数据
  260. /// TCP - 顺序发送所有数据包
  261. /// </summary>
  262. /// <param name="pBuffers">发送缓冲区数组</param>
  263. /// <param name="iCount">发送缓冲区数目</param>
  264. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  265. public bool SendPackets(WSABUF[] buffers, int count)
  266. {
  267. return Sdk.HP_Client_SendPackets(pClient, buffers, count);
  268. }
  269. /// <summary>
  270. /// 发送多组数据
  271. /// 向指定连接发送多组数据
  272. /// TCP - 顺序发送所有数据包
  273. /// </summary>
  274. /// <param name="pBuffers">发送缓冲区数组</param>
  275. /// <param name="iCount">发送缓冲区数目</param>
  276. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  277. public bool SendPackets<T>(T[] objects)
  278. {
  279. bool ret = false;
  280. WSABUF[] buffer = new WSABUF[objects.Length];
  281. IntPtr[] ptrs = new IntPtr[buffer.Length];
  282. try
  283. {
  284. for (int i = 0; i < objects.Length; i++)
  285. {
  286. buffer[i].Length = Marshal.SizeOf(typeof(T));
  287. ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length);
  288. Marshal.StructureToPtr(objects[i], ptrs[i], true);
  289. buffer[i].Buffer = ptrs[i];
  290. }
  291. ret = SendPackets(buffer, buffer.Length);
  292. }
  293. catch (Exception ex)
  294. {
  295. throw ex;
  296. }
  297. finally
  298. {
  299. for (int i = 0; i < ptrs.Length; i++)
  300. {
  301. if (ptrs[i] != IntPtr.Zero)
  302. {
  303. Marshal.FreeHGlobal(ptrs[i]);
  304. }
  305. }
  306. }
  307. return ret;
  308. }
  309. /// <summary>
  310. /// 名称:发送小文件
  311. /// 描述:向指定连接发送 4096 KB 以下的小文件
  312. /// </summary>
  313. /// <param name="filePath">文件路径</param>
  314. /// <param name="head">头部附加数据</param>
  315. /// <param name="tail">尾部附加数据</param>
  316. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  317. public bool SendSmallFile(string filePath, ref WSABUF head, ref WSABUF tail)
  318. {
  319. return Sdk.HP_TcpClient_SendSmallFile(pClient, filePath, ref head, ref tail);
  320. }
  321. /// <summary>
  322. /// 名称:发送小文件
  323. /// 描述:向指定连接发送 4096 KB 以下的小文件
  324. /// </summary>
  325. /// <param name="filePath">文件路径</param>
  326. /// <param name="head">头部附加数据,可以为null</param>
  327. /// <param name="tail">尾部附加数据,可以为null</param>
  328. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  329. public bool SendSmallFile(string filePath, byte[] head, byte[] tail)
  330. {
  331. IntPtr pHead = IntPtr.Zero;
  332. IntPtr pTail = IntPtr.Zero;
  333. WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead };
  334. WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail };
  335. if (head != null)
  336. {
  337. wsaHead.Length = head.Length;
  338. wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0);
  339. }
  340. if (tail != null)
  341. {
  342. wsaHead.Length = tail.Length;
  343. wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0);
  344. }
  345. return SendSmallFile(filePath, ref wsaHead, ref wsatail);
  346. }
  347. /// <summary>
  348. /// 名称:发送小文件
  349. /// 描述:向指定连接发送 4096 KB 以下的小文件
  350. /// </summary>
  351. /// <param name="filePath">文件路径</param>
  352. /// <param name="head">头部附加数据,可以为null</param>
  353. /// <param name="tail">尾部附加数据,可以为null</param>
  354. /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns>
  355. public bool SendSmallFile<T1, T2>(string filePath, T1 head, T2 tail)
  356. {
  357. byte[] headBuffer = null;
  358. if (head != null)
  359. {
  360. headBuffer = StructureToByte<T1>(head);
  361. }
  362. byte[] tailBuffer = null;
  363. if (tail != null)
  364. {
  365. tailBuffer = StructureToByte<T2>(tail);
  366. }
  367. return SendSmallFile(filePath, headBuffer, tailBuffer);
  368. }
  369. /// <summary>
  370. /// 获取错误码
  371. /// </summary>
  372. public SocketError ErrorCode
  373. {
  374. get
  375. {
  376. return Sdk.HP_Client_GetLastError(pClient);
  377. }
  378. }
  379. /// <summary>
  380. /// 版本号
  381. /// </summary>
  382. public string Version
  383. {
  384. get
  385. {
  386. return Sdk.GetHPSocketVersion();
  387. }
  388. }
  389. /// <summary>
  390. /// 获取错误信息
  391. /// </summary>
  392. public string ErrorMessage
  393. {
  394. get
  395. {
  396. IntPtr ptr = Sdk.HP_Client_GetLastErrorDesc(pClient);
  397. string desc = Marshal.PtrToStringAnsi(ptr);
  398. return desc;
  399. }
  400. }
  401. /// <summary>
  402. /// 获取或设置接收状态
  403. /// </summary>
  404. public ReceiveState ReceiveState
  405. {
  406. get
  407. {
  408. int state = -1;
  409. if (Sdk.HP_Client_IsPauseReceive(pClient, ref state))
  410. {
  411. return (ReceiveState)state;
  412. }
  413. return ReceiveState.Unknown;
  414. }
  415. set
  416. {
  417. Sdk.HP_Client_PauseReceive(pClient, (int)value);
  418. }
  419. }
  420. /// <summary>
  421. /// </summary>
  422. /// <param name="length"></param>
  423. /// <returns></returns>
  424. public bool GetPendingDataLength(ref int length)
  425. {
  426. return Sdk.HP_Client_GetPendingDataLength(pClient, ref length);
  427. }
  428. /// <summary>
  429. /// 获取附加数据
  430. /// </summary>
  431. /// <returns></returns>
  432. public T GetExtra<T>()
  433. {
  434. return (T)ExtraData.GetExtra(pClient);
  435. }
  436. /// <summary>
  437. /// 设置附加数据
  438. ///
  439. /// </summary>
  440. /// <param name="value"></param>
  441. /// <returns></returns>
  442. public bool SetExtra(object newValue)
  443. {
  444. return ExtraData.SetExtra(pClient, newValue);
  445. }
  446. /// <summary>
  447. /// 删除附加数据
  448. /// </summary>
  449. /// <param name="key"></param>
  450. /// <returns></returns>
  451. public bool RemoveExtra()
  452. {
  453. return ExtraData.RemoveExtra(pClient);
  454. }
  455. ///// <summary>
  456. ///// 设置连接的附加数据
  457. ///// </summary>
  458. ///// <param name="obj">如果为null,则为释放设置的数据</param>
  459. ///// <returns></returns>
  460. //public void SetExtra(object obj)
  461. //{
  462. // // 释放附加数据
  463. // IntPtr ptr = Sdk.HP_Client_GetExtra(pClient);
  464. // if (ptr != IntPtr.Zero)
  465. // {
  466. // Marshal.FreeHGlobal(ptr);
  467. // ptr = IntPtr.Zero;
  468. // }
  469. // if (obj != null)
  470. // {
  471. // // 设置附加数据
  472. // ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
  473. // Marshal.StructureToPtr(obj, ptr, false);
  474. // }
  475. // Sdk.HP_Client_SetExtra(pClient, ptr);
  476. //}
  477. ///// <summary>
  478. ///// 获取附加数据
  479. ///// 如设置的是个结构体/类对象,可以用 Type objA = (Type)Marshal.PtrToStructure(ptr, typeof(Type)) 获取
  480. ///// 其中Type是结构体/类名,ptr是该方法的传出值,在该方法返回为true的时候可用
  481. ///// </summary>
  482. ///// <param name="ptr"></param>
  483. ///// <returns></returns>
  484. //public T GetExtra<T>()
  485. //{
  486. // IntPtr ptr = Sdk.HP_Client_GetExtra(pClient);
  487. // T obj = default(T);
  488. // if (ptr != IntPtr.Zero)
  489. // {
  490. // obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
  491. // }
  492. // return obj;
  493. //}
  494. ///// <summary>
  495. ///// 移除连接中的附加数据, 同SetExtra(null)
  496. ///// </summary>
  497. ///// <returns></returns>
  498. //public void RemoveExtra()
  499. //{
  500. // SetExtra(null);
  501. //}
  502. ///// <summary>
  503. ///// 获取或这是附加数据
  504. ///// 推荐使用泛型方法:T GetExtra<T>()
  505. ///// </summary>
  506. //public object Extra
  507. //{
  508. // get
  509. // {
  510. // return GetExtra<object>();
  511. // }
  512. // set
  513. // {
  514. // SetExtra(value);
  515. // }
  516. //}
  517. /// <summary>
  518. /// 获取监听socket的地址信息
  519. /// </summary>
  520. /// <param name="ip"></param>
  521. /// <param name="ipLength"></param>
  522. /// <param name="port"></param>
  523. /// <returns></returns>
  524. public bool GetListenAddress(ref string ip, ref ushort port)
  525. {
  526. int ipLength = 40;
  527. StringBuilder sb = new StringBuilder(ipLength);
  528. bool ret = Sdk.HP_Client_GetLocalAddress(pClient, sb, ref ipLength, ref port);
  529. if (ret == true)
  530. {
  531. ip = sb.ToString();
  532. }
  533. return ret;
  534. }
  535. /// <summary>
  536. /// 获取连接的远程主机信息
  537. /// </summary>
  538. /// <param name="host"></param>
  539. /// <param name="port"></param>
  540. /// <returns></returns>
  541. public bool GetRemoteHost(ref string host, ref ushort port)
  542. {
  543. int ipLength = 40;
  544. StringBuilder sb = new StringBuilder(ipLength);
  545. bool ret = Sdk.HP_Client_GetRemoteHost(pClient, sb, ref ipLength, ref port);
  546. if (ret == true)
  547. {
  548. host = sb.ToString();
  549. }
  550. return ret;
  551. }
  552. /// <summary>
  553. /// 是否启动
  554. /// </summary>
  555. public bool IsStarted
  556. {
  557. get
  558. {
  559. if (pClient == IntPtr.Zero)
  560. {
  561. return false;
  562. }
  563. return Sdk.HP_Client_HasStarted(pClient);
  564. }
  565. }
  566. /// <summary>
  567. /// 状态
  568. /// </summary>
  569. public ServiceState State
  570. {
  571. get
  572. {
  573. return Sdk.HP_Client_GetState(pClient);
  574. }
  575. }
  576. /// <summary>
  577. /// 获取该组件对象的连接Id
  578. /// </summary>
  579. public IntPtr ConnectionId
  580. {
  581. get
  582. {
  583. return Sdk.HP_Client_GetConnectionID(pClient);
  584. }
  585. }
  586. /// <summary>
  587. /// 检测是否为安全连接(SSL/HTTPS)
  588. /// </summary>
  589. public bool IsSecure
  590. {
  591. get
  592. {
  593. return Sdk.HP_Client_IsSecure(pClient);
  594. }
  595. }
  596. ///////////////////////////////////////////////////////////////////////////////////////
  597. /// <summary>
  598. /// 读取或设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 )
  599. /// </summary>
  600. public uint FreeBufferPoolSize
  601. {
  602. get
  603. {
  604. return Sdk.HP_Client_GetFreeBufferPoolSize(pClient);
  605. }
  606. set
  607. {
  608. Sdk.HP_Client_SetFreeBufferPoolSize(pClient, value);
  609. }
  610. }
  611. /// <summary>
  612. /// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍)
  613. /// </summary>
  614. public uint FreeBufferPoolHold
  615. {
  616. get
  617. {
  618. return Sdk.HP_Client_GetFreeBufferPoolHold(pClient);
  619. }
  620. set
  621. {
  622. Sdk.HP_Client_SetFreeBufferPoolHold(pClient, value);
  623. }
  624. }
  625. ///////////////////////////////////////////////////////////////////////////////////////
  626. /// <summary>
  627. /// 读取或设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj))
  628. /// </summary>
  629. public uint SocketBufferSize
  630. {
  631. get
  632. {
  633. return Sdk.HP_TcpClient_GetSocketBufferSize(pClient);
  634. }
  635. set
  636. {
  637. Sdk.HP_TcpClient_SetSocketBufferSize(pClient, value);
  638. }
  639. }
  640. /// <summary>
  641. /// 读取或设置心跳包间隔(毫秒,0 则不发送心跳包)
  642. /// </summary>
  643. public uint KeepAliveTime
  644. {
  645. get
  646. {
  647. return Sdk.HP_TcpClient_GetKeepAliveTime(pClient);
  648. }
  649. set
  650. {
  651. Sdk.HP_TcpClient_SetKeepAliveTime(pClient, value);
  652. }
  653. }
  654. /// <summary>
  655. /// 读取或设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线)
  656. /// </summary>
  657. public uint KeepAliveInterval
  658. {
  659. get
  660. {
  661. return Sdk.HP_TcpClient_GetKeepAliveInterval(pClient);
  662. }
  663. set
  664. {
  665. Sdk.HP_TcpClient_SetKeepAliveInterval(pClient, value);
  666. }
  667. }
  668. /// <summary>
  669. /// 根据错误码返回错误信息
  670. /// </summary>
  671. /// <param name="code"></param>
  672. /// <returns></returns>
  673. public string GetSocketErrorDesc(SocketError code)
  674. {
  675. IntPtr ptr = Sdk.HP_GetSocketErrorDesc(code);
  676. string desc = Marshal.PtrToStringAnsi(ptr);
  677. return desc;
  678. }
  679. ///////////////////////////////////////////////////////////////////////////////////////
  680. protected Sdk.OnPrepareConnect _OnPrepareConnect = null;
  681. protected Sdk.OnConnect _OnConnect = null;
  682. protected Sdk.OnReceive _OnReceive = null;
  683. protected Sdk.OnSend _OnSend = null;
  684. protected Sdk.OnClose _OnClose = null;
  685. protected Sdk.OnHandShake _OnHandShake = null;
  686. /// <summary>
  687. /// 设置回调函数
  688. /// </summary>
  689. protected virtual void SetCallback()
  690. {
  691. // 设置 Socket 监听器回调函数
  692. _OnPrepareConnect = new Sdk.OnPrepareConnect(SDK_OnPrepareConnect);
  693. _OnConnect = new Sdk.OnConnect(SDK_OnConnect);
  694. _OnSend = new Sdk.OnSend(SDK_OnSend);
  695. _OnReceive = new Sdk.OnReceive(SDK_OnReceive);
  696. _OnClose = new Sdk.OnClose(SDK_OnClose);
  697. _OnHandShake = new Sdk.OnHandShake(SDK_OnHandShake);
  698. Sdk.HP_Set_FN_Client_OnPrepareConnect(pListener, _OnPrepareConnect);
  699. Sdk.HP_Set_FN_Client_OnConnect(pListener, _OnConnect);
  700. Sdk.HP_Set_FN_Client_OnSend(pListener, _OnSend);
  701. Sdk.HP_Set_FN_Client_OnReceive(pListener, _OnReceive);
  702. Sdk.HP_Set_FN_Client_OnClose(pListener, _OnClose);
  703. Sdk.HP_Set_FN_Client_OnHandShake(pListener, _OnHandShake);
  704. }
  705. protected HandleResult SDK_OnPrepareConnect(IntPtr pSender, IntPtr connId, IntPtr socket)
  706. {
  707. if (OnPrepareConnect != null)
  708. {
  709. return OnPrepareConnect(this, socket);
  710. }
  711. return HandleResult.Ignore;
  712. }
  713. protected HandleResult SDK_OnConnect(IntPtr pSender, IntPtr connId)
  714. {
  715. if (OnConnect != null)
  716. {
  717. return OnConnect(this);
  718. }
  719. return HandleResult.Ignore;
  720. }
  721. protected HandleResult SDK_OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length)
  722. {
  723. if (OnSend != null)
  724. {
  725. byte[] bytes = new byte[length];
  726. Marshal.Copy(pData, bytes, 0, length);
  727. return OnSend(this, bytes);
  728. }
  729. return HandleResult.Ignore;
  730. }
  731. protected HandleResult SDK_OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length)
  732. {
  733. if (OnPointerDataReceive != null)
  734. {
  735. return OnPointerDataReceive(this, pData, length);
  736. }
  737. else if (OnReceive != null)
  738. {
  739. byte[] bytes = new byte[length];
  740. Marshal.Copy(pData, bytes, 0, length);
  741. return OnReceive(this, bytes);
  742. }
  743. return HandleResult.Ignore;
  744. }
  745. protected HandleResult SDK_OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode)
  746. {
  747. if (OnClose != null)
  748. {
  749. return OnClose(this, enOperation, errorCode);
  750. }
  751. return HandleResult.Ignore;
  752. }
  753. protected HandleResult SDK_OnHandShake(IntPtr pSender, IntPtr connId)
  754. {
  755. if (OnHandShake != null)
  756. {
  757. return OnHandShake(this);
  758. }
  759. return HandleResult.Ignore;
  760. }
  761. ///////////////////////////////////////////////////////////////////////////
  762. /// <summary>
  763. /// 获取系统返回的错误码
  764. /// </summary>
  765. public int SYSGetLastError()
  766. {
  767. return Sdk.SYS_GetLastError();
  768. }
  769. /// <summary>
  770. /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码
  771. /// </summary>
  772. public int SYSWSAGetLastError()
  773. {
  774. return Sdk.SYS_WSAGetLastError();
  775. }
  776. /// <summary>
  777. /// 调用系统的 setsockopt()
  778. /// </summary>
  779. /// <param name="sock"></param>
  780. /// <param name="level"></param>
  781. /// <param name="name"></param>
  782. /// <param name="val"></param>
  783. /// <param name="len"></param>
  784. /// <returns></returns>
  785. ///
  786. public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len)
  787. {
  788. return Sdk.SYS_SetSocketOption(sock, level, name, val, len);
  789. }
  790. /// <summary>
  791. /// 调用系统的 getsockopt()
  792. /// </summary>
  793. /// <param name="sock"></param>
  794. /// <param name="level"></param>
  795. /// <param name="name"></param>
  796. /// <param name="val"></param>
  797. /// <param name="len"></param>
  798. /// <returns></returns>
  799. ///
  800. public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len)
  801. {
  802. return Sdk.SYS_GetSocketOption(sock, level, name, val, ref len);
  803. }
  804. /// <summary>
  805. /// 调用系统的 ioctlsocket()
  806. /// </summary>
  807. /// <param name="sock"></param>
  808. /// <param name="cmd"></param>
  809. /// <param name="arg"></param>
  810. /// <returns></returns>
  811. ///
  812. public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg)
  813. {
  814. return Sdk.SYS_IoctlSocket(sock, cmd, arg);
  815. }
  816. /// <summary>
  817. /// 调用系统的 ::WSAIoctl()
  818. /// </summary>
  819. /// <param name="sock"></param>
  820. /// <param name="dwIoControlCode"></param>
  821. /// <param name="lpvInBuffer"></param>
  822. /// <param name="cbInBuffer"></param>
  823. /// <param name="lpvOutBuffer"></param>
  824. /// <param name="cbOutBuffer"></param>
  825. /// <param name="lpcbBytesReturned"></param>
  826. /// <returns></returns>
  827. public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer,
  828. IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned)
  829. {
  830. return Sdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer,
  831. lpvOutBuffer, cbOutBuffer, lpcbBytesReturned);
  832. }
  833. /// <summary>
  834. /// 由结构体转换为byte数组
  835. /// </summary>
  836. public byte[] StructureToByte<T>(T structure)
  837. {
  838. int size = Marshal.SizeOf(typeof(T));
  839. byte[] buffer = new byte[size];
  840. IntPtr bufferIntPtr = Marshal.AllocHGlobal(size);
  841. try
  842. {
  843. Marshal.StructureToPtr(structure, bufferIntPtr, true);
  844. Marshal.Copy(bufferIntPtr, buffer, 0, size);
  845. }
  846. finally
  847. {
  848. Marshal.FreeHGlobal(bufferIntPtr);
  849. }
  850. return buffer;
  851. }
  852. /// <summary>
  853. /// 由byte数组转换为结构体
  854. /// </summary>
  855. public T ByteToStructure<T>(byte[] dataBuffer)
  856. {
  857. object structure = null;
  858. int size = Marshal.SizeOf(typeof(T));
  859. IntPtr allocIntPtr = Marshal.AllocHGlobal(size);
  860. try
  861. {
  862. Marshal.Copy(dataBuffer, 0, allocIntPtr, size);
  863. structure = Marshal.PtrToStructure(allocIntPtr, typeof(T));
  864. }
  865. finally
  866. {
  867. Marshal.FreeHGlobal(allocIntPtr);
  868. }
  869. return (T)structure;
  870. }
  871. /// <summary>
  872. /// 对象序列化成byte[]
  873. /// </summary>
  874. /// <param name="obj"></param>
  875. /// <returns></returns>
  876. public byte[] ObjectToBytes(object obj)
  877. {
  878. using (MemoryStream ms = new MemoryStream())
  879. {
  880. IFormatter formatter = new BinaryFormatter();
  881. formatter.Serialize(ms, obj);
  882. return ms.GetBuffer();
  883. }
  884. }
  885. /// <summary>
  886. /// byte[]序列化成对象
  887. /// </summary>
  888. /// <param name="Bytes"></param>
  889. /// <returns></returns>
  890. public object BytesToObject(byte[] bytes)
  891. {
  892. using (MemoryStream ms = new MemoryStream(bytes))
  893. {
  894. IFormatter formatter = new BinaryFormatter();
  895. return formatter.Deserialize(ms);
  896. }
  897. }
  898. /// <summary>
  899. /// byte[]转结构体
  900. /// </summary>
  901. /// <typeparam name="T"></typeparam>
  902. /// <param name="bytes"></param>
  903. /// <returns></returns>
  904. public T BytesToStruct<T>(byte[] bytes)
  905. {
  906. Type strcutType = typeof(T);
  907. int size = Marshal.SizeOf(strcutType);
  908. IntPtr buffer = Marshal.AllocHGlobal(size);
  909. try
  910. {
  911. Marshal.Copy(bytes, 0, buffer, size);
  912. return (T)Marshal.PtrToStructure(buffer, strcutType);
  913. }
  914. finally
  915. {
  916. Marshal.FreeHGlobal(buffer);
  917. }
  918. }
  919. }
  920. }