SocketHelper.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 4.2.1
  5. * Author : Bruce Liang
  6. * Website : http://www.jessma.org
  7. * Project : https://github.com/ldcsaa
  8. * Blog : http://www.cnblogs.com/ldcsaa
  9. * Wiki : http://www.oschina.net/p/hp-socket
  10. * QQ Group : 75375912
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. #pragma once
  25. #include <ws2tcpip.h>
  26. #include <mswsock.h>
  27. #include <malloc.h>
  28. #include <atlfile.h>
  29. #include "SocketInterface.h"
  30. #include "../../Common/Src/WaitFor.h"
  31. #include "../../Common/Src/bufferpool.h"
  32. #include "../../Common/Src/RingBuffer.h"
  33. /************************************************************************
  34. 名称:全局常量
  35. 描述:声明组件的公共全局常量
  36. ************************************************************************/
  37. /* HP-Socket 版本号 */
  38. #define HP_VERSION_MAJOR 4
  39. #define HP_VERSION_MINOR 2
  40. #define HP_VERSION_REVISE 1
  41. #define HP_VERSION_BUILD 5
  42. /* IOCP 最大工作线程数 */
  43. #define MAX_WORKER_THREAD_COUNT 500
  44. /* IOCP Socket 缓冲区最小值 */
  45. #define MIN_SOCKET_BUFFER_SIZE 64
  46. /* 小文件最大字节数 */
  47. #define MAX_SMALL_FILE_SIZE 0x3FFFFF
  48. /* 最大连接时长 */
  49. #define MAX_CONNECTION_PERIOD (MAXLONG / 2)
  50. /* Server/Agent 默认最大连接数 */
  51. #define DEFAULT_MAX_CONNECTION_COUNT 10000
  52. /* Server/Agent 默认 IOCP 工作线程数 */
  53. #define DEFAULT_WORKER_THREAD_COUNT GetDefaultWorkerThreadCount()
  54. /* Server/Agent 默认 Socket 缓存对象锁定时间 */
  55. #define DEFAULT_FREE_SOCKETOBJ_LOCK_TIME (10 * 1000)
  56. /* Server/Agent 默认 Socket 缓存池大小 */
  57. #define DEFAULT_FREE_SOCKETOBJ_POOL 150
  58. /* Server/Agent 默认 Socket 缓存池回收阀值 */
  59. #define DEFAULT_FREE_SOCKETOBJ_HOLD 600
  60. /* Server/Agent 默认内存块缓存池大小 */
  61. #define DEFAULT_FREE_BUFFEROBJ_POOL 300
  62. /* Server/Agent 默认内存块缓存池回收阀值 */
  63. #define DEFAULT_FREE_BUFFEROBJ_HOLD 1200
  64. /* Client 默认内存块缓存池大小 */
  65. #define DEFAULT_CLIENT_FREE_BUFFER_POOL_SIZE 10
  66. /* Client 默认内存块缓存池回收阀值 */
  67. #define DEFAULT_CLIENT_FREE_BUFFER_POOL_HOLD 40
  68. /* Agent 默认绑定地址 */
  69. #define DEFAULT_BIND_ADDRESS _T("0.0.0.0")
  70. /* TCP 默认通信数据缓冲区大小 */
  71. #define DEFAULT_TCP_SOCKET_BUFFER_SIZE GetDefaultTcpSocketBufferSize()
  72. /* TCP 默认心跳包间隔 */
  73. #define DEFALUT_TCP_KEEPALIVE_TIME (30 * 1000)
  74. /* TCP 默认心跳确认包检测间隔 */
  75. #define DEFALUT_TCP_KEEPALIVE_INTERVAL (10 * 1000)
  76. /* TCP Server 默认 Listen 队列大小 */
  77. #define DEFAULT_TCP_SERVER_SOCKET_LISTEN_QUEUE SOMAXCONN
  78. /* TCP Server 默认预投递 Accept 数量 */
  79. #define DEFAULT_TCP_SERVER_ACCEPT_SOCKET_COUNT 300
  80. /* UDP 默认数据报文最大长度 */
  81. #define DEFAULT_UDP_MAX_DATAGRAM_SIZE 1472
  82. /* UDP 默认 Receive 预投递数量 */
  83. #define DEFAULT_UDP_POST_RECEIVE_COUNT 300
  84. /* UDP 默认监测包尝试次数 */
  85. #define DEFAULT_UDP_DETECT_ATTEMPTS 3
  86. /* UDP 默认监测包发送间隔 */
  87. #define DEFAULT_UDP_DETECT_INTERVAL 20
  88. /* TCP Pack 包长度位数 */
  89. #define TCP_PACK_LENGTH_BITS 22
  90. /* TCP Pack 包长度掩码 */
  91. #define TCP_PACK_LENGTH_MASK 0x3FFFFF
  92. /* TCP Pack 包最大长度硬限制 */
  93. #define TCP_PACK_MAX_SIZE_LIMIT 0x3FFFFF
  94. /* TCP Pack 包默认最大长度 */
  95. #define TCP_PACK_DEFAULT_MAX_SIZE 0x040000
  96. /* TCP Pack 包头标识值硬限制 */
  97. #define TCP_PACK_HEADER_FLAG_LIMIT 0x0003FF
  98. /* TCP Pack 包头默认标识值 */
  99. #define TCP_PACK_DEFAULT_HEADER_FLAG 0x000000
  100. DWORD GetDefaultWorkerThreadCount();
  101. DWORD GetDefaultTcpSocketBufferSize();
  102. /************************************************************************
  103. 名称:Windows Socket 组件初始化类
  104. 描述:自动加载和卸载 Windows Socket 组件
  105. ************************************************************************/
  106. class CInitSocket
  107. {
  108. public:
  109. CInitSocket(LPWSADATA lpWSAData = nullptr, BYTE minorVersion = 2, BYTE majorVersion = 2)
  110. {
  111. LPWSADATA lpTemp = lpWSAData;
  112. if(!lpTemp)
  113. lpTemp = (LPWSADATA)_alloca(sizeof(WSADATA));
  114. m_iResult = ::WSAStartup(MAKEWORD(majorVersion, minorVersion), lpTemp);
  115. }
  116. ~CInitSocket()
  117. {
  118. if(IsValid())
  119. ::WSACleanup();
  120. }
  121. int GetResult() {return m_iResult;}
  122. BOOL IsValid() {return m_iResult == 0;}
  123. private:
  124. int m_iResult;
  125. };
  126. /* Server 组件和 Agent 组件内部使用的事件处理结果常量 */
  127. // 连接已关闭
  128. #define HR_CLOSED 0xFF
  129. /* 关闭连接标识 */
  130. enum EnSocketCloseFlag
  131. {
  132. SCF_NONE = 0, // 不触发事件
  133. SCF_CLOSE = 1, // 触发 正常关闭 OnClose 事件
  134. SCF_ERROR = 2 // 触发 异常关闭 OnClose 事件
  135. };
  136. /* 数据缓冲区基础结构 */
  137. template<class T> struct TBufferObjBase
  138. {
  139. WSAOVERLAPPED ov;
  140. EnSocketOperation operation;
  141. WSABUF buff;
  142. int capacity;
  143. CPrivateHeap& heap;
  144. T* next;
  145. T* last;
  146. static T* Construct(CPrivateHeap& heap, DWORD dwCapacity)
  147. {
  148. T* pBufferObj = (T*)heap.Alloc(sizeof(T) + dwCapacity);
  149. ASSERT(pBufferObj);
  150. ZeroMemory(pBufferObj, sizeof(T));
  151. pBufferObj->TBufferObjBase::TBufferObjBase(heap, dwCapacity);
  152. pBufferObj->buff.buf = ((char*)pBufferObj) + sizeof(T);
  153. return pBufferObj;
  154. }
  155. static void Destruct(T* pBufferObj)
  156. {
  157. ASSERT(pBufferObj);
  158. pBufferObj->heap.Free(pBufferObj);
  159. }
  160. TBufferObjBase(CPrivateHeap& hp, DWORD dwCapacity)
  161. : heap(hp)
  162. , capacity((int)dwCapacity)
  163. {
  164. ASSERT(capacity > 0);
  165. }
  166. int Cat(const BYTE* pData, int length)
  167. {
  168. ASSERT(pData != nullptr && length > 0);
  169. int cat = min(Remain(), length);
  170. if(cat > 0)
  171. {
  172. memcpy(buff.buf + buff.len, pData, cat);
  173. buff.len += cat;
  174. }
  175. return cat;
  176. }
  177. void Reset() {buff.len = 0;}
  178. int Remain() {return capacity - buff.len;}
  179. BOOL IsFull() {return buff.len == capacity;}
  180. };
  181. /* 数据缓冲区结构 */
  182. struct TBufferObj : public TBufferObjBase<TBufferObj>
  183. {
  184. SOCKET client;
  185. };
  186. /* UDP 数据缓冲区结构 */
  187. struct TUdpBufferObj : public TBufferObjBase<TUdpBufferObj>
  188. {
  189. SOCKADDR_IN remoteAddr;
  190. int addrLen;
  191. };
  192. /* 数据缓冲区链表模板 */
  193. template<class T> struct TBufferObjListT : public TSimpleList<T>
  194. {
  195. public:
  196. int Cat(const BYTE* pData, int length)
  197. {
  198. ASSERT(pData != nullptr && length > 0);
  199. int remain = length;
  200. while(remain > 0)
  201. {
  202. T* pItem = Back();
  203. if(pItem == nullptr || pItem->IsFull())
  204. pItem = PushBack(bfPool.PickFreeItem());
  205. int cat = pItem->Cat(pData, remain);
  206. pData += cat;
  207. remain -= cat;
  208. }
  209. return length;
  210. }
  211. T* PushTail(const BYTE* pData, int length)
  212. {
  213. ASSERT(pData != nullptr && length > 0 && length <= (int)bfPool.GetItemCapacity());
  214. T* pItem = PushBack(bfPool.PickFreeItem());
  215. pItem->Cat(pData, length);
  216. return pItem;
  217. }
  218. void Release()
  219. {
  220. bfPool.PutFreeItem(*this);
  221. }
  222. public:
  223. TBufferObjListT(CNodePoolT<T>& pool) : bfPool(pool)
  224. {
  225. }
  226. private:
  227. CNodePoolT<T>& bfPool;
  228. };
  229. /* 数据缓冲区对象池 */
  230. typedef CNodePoolT<TBufferObj> CBufferObjPool;
  231. /* UDP 数据缓冲区对象池 */
  232. typedef CNodePoolT<TUdpBufferObj> CUdpBufferObjPool;
  233. /* 数据缓冲区链表模板 */
  234. typedef TBufferObjListT<TBufferObj> TBufferObjList;
  235. /* UDP 数据缓冲区链表模板 */
  236. typedef TBufferObjListT<TUdpBufferObj> TUdpBufferObjList;
  237. /* 数据缓冲区结构链表 */
  238. typedef CRingPool<TBufferObj> TBufferObjPtrList;
  239. /* Udp 数据缓冲区结构链表 */
  240. typedef CRingPool<TUdpBufferObj> TUdpBufferObjPtrList;
  241. /* Socket 缓冲区基础结构 */
  242. struct TSocketObjBase
  243. {
  244. CONNID connID;
  245. SOCKADDR_IN remoteAddr;
  246. PVOID extra;
  247. PVOID reserved;
  248. PVOID reserved2;
  249. BOOL valid;
  250. union
  251. {
  252. DWORD freeTime;
  253. DWORD connTime;
  254. };
  255. DWORD activeTime;
  256. CCriSec csSend;
  257. volatile BOOL smooth;
  258. volatile long pending;
  259. volatile long sndCount;
  260. CReentrantSpinGuard csRecv;
  261. static BOOL IsExist(TSocketObjBase* pSocketObj)
  262. {return pSocketObj != nullptr;}
  263. static BOOL IsValid(TSocketObjBase* pSocketObj)
  264. {return pSocketObj != nullptr && pSocketObj->valid;}
  265. static void Invalid(TSocketObjBase* pSocketObj)
  266. {ASSERT(IsExist(pSocketObj)); pSocketObj->valid = FALSE;}
  267. static BOOL IsSmooth(TSocketObjBase* pSocketObj)
  268. {ASSERT(IsExist(pSocketObj)); return pSocketObj->valid && pSocketObj->smooth;}
  269. static BOOL IsPending(TSocketObjBase* pSocketObj)
  270. {ASSERT(IsExist(pSocketObj)); return pSocketObj->valid && pSocketObj->pending > 0;}
  271. static void Release(TSocketObjBase* pSocketObj)
  272. {
  273. ASSERT(IsExist(pSocketObj));
  274. pSocketObj->freeTime = ::TimeGetTime();
  275. }
  276. int Pending() {return pending;}
  277. void Reset(CONNID dwConnID)
  278. {
  279. connID = dwConnID;
  280. valid = TRUE;
  281. smooth = TRUE;
  282. pending = 0;
  283. sndCount = 0;
  284. extra = nullptr;
  285. reserved = nullptr;
  286. reserved2= nullptr;
  287. }
  288. };
  289. /* 数据缓冲区结构 */
  290. struct TSocketObj : public TSocketObjBase
  291. {
  292. SOCKET socket;
  293. CStringA host;
  294. TBufferObjList sndBuff;
  295. TSocketObj(CBufferObjPool& bfPool)
  296. : sndBuff(bfPool)
  297. {
  298. }
  299. static void Release(TSocketObj* pSocketObj)
  300. {
  301. __super::Release(pSocketObj);
  302. pSocketObj->sndBuff.Release();
  303. }
  304. void Reset(CONNID dwConnID, SOCKET soClient)
  305. {
  306. __super::Reset(dwConnID);
  307. host.Empty();
  308. socket = soClient;
  309. }
  310. BOOL GetRemoteHost(LPCSTR* lpszHost, USHORT* pusPort = nullptr)
  311. {
  312. *lpszHost = host;
  313. if(pusPort)
  314. *pusPort = ntohs(remoteAddr.sin_port);
  315. return (*lpszHost != nullptr && (*lpszHost)[0] != 0);
  316. }
  317. };
  318. /* UDP 数据缓冲区结构 */
  319. struct TUdpSocketObj : public TSocketObjBase
  320. {
  321. TUdpBufferObjList sndBuff;
  322. volatile DWORD detectFails;
  323. TUdpSocketObj(CUdpBufferObjPool& bfPool)
  324. : sndBuff(bfPool)
  325. {
  326. }
  327. static void Release(TUdpSocketObj* pSocketObj)
  328. {
  329. __super::Release(pSocketObj);
  330. pSocketObj->sndBuff.Release();
  331. }
  332. void Reset(CONNID dwConnID)
  333. {
  334. __super::Reset(dwConnID);
  335. detectFails = 0;
  336. }
  337. };
  338. /* 有效 TSocketObj 缓存 */
  339. typedef CRingCache2<TSocketObj, CONNID, true> TSocketObjPtrPool;
  340. /* 失效 TSocketObj 缓存 */
  341. typedef CRingPool<TSocketObj> TSocketObjPtrList;
  342. /* 失效 TSocketObj 垃圾回收结构链表 */
  343. typedef CCASQueue<TSocketObj> TSocketObjPtrQueue;
  344. /* 有效 TUdpSocketObj 缓存 */
  345. typedef CRingCache2<TUdpSocketObj, CONNID, true> TUdpSocketObjPtrPool;
  346. /* 失效 TUdpSocketObj 缓存 */
  347. typedef CRingPool<TUdpSocketObj> TUdpSocketObjPtrList;
  348. /* 失效 TUdpSocketObj 垃圾回收结构链表 */
  349. typedef CCASQueue<TUdpSocketObj> TUdpSocketObjPtrQueue;
  350. /* SOCKADDR_IN 比较器 */
  351. struct sockaddr_func
  352. {
  353. struct hash
  354. {
  355. size_t operator() (const SOCKADDR_IN* pA) const
  356. {
  357. return ((pA->sin_family << 16) | ntohs(pA->sin_port)) ^ pA->sin_addr.s_addr;
  358. }
  359. };
  360. struct equal_to
  361. {
  362. bool operator () (const SOCKADDR_IN* pA, const SOCKADDR_IN* pB) const
  363. {
  364. return memcmp(pA, pB, offsetof(SOCKADDR_IN, sin_zero)) == 0;
  365. }
  366. };
  367. };
  368. /* 地址-连接 ID 哈希表 */
  369. typedef unordered_map<SOCKADDR_IN*, CONNID, sockaddr_func::hash, sockaddr_func::equal_to>
  370. TSockAddrMap;
  371. /* 地址-连接 ID 哈希表迭代器 */
  372. typedef TSockAddrMap::iterator TSockAddrMapI;
  373. /* 地址-连接 ID 哈希表 const 迭代器 */
  374. typedef TSockAddrMap::const_iterator TSockAddrMapCI;
  375. /* IClient 组件关闭上下文 */
  376. struct TClientCloseContext
  377. {
  378. BOOL bFireOnClose;
  379. EnSocketOperation enOperation;
  380. int iErrorCode;
  381. TClientCloseContext(BOOL bFire = TRUE, EnSocketOperation enOp = SO_CLOSE, int iCode = SE_OK)
  382. {
  383. Reset(bFire, enOp, iCode);
  384. }
  385. void Reset(BOOL bFire = TRUE, EnSocketOperation enOp = SO_CLOSE, int iCode = SE_OK)
  386. {
  387. bFireOnClose = bFire;
  388. enOperation = enOp;
  389. iErrorCode = iCode;
  390. }
  391. };
  392. /*****************************************************************************************************/
  393. /******************************************** 公共帮助方法 ********************************************/
  394. /*****************************************************************************************************/
  395. // 获取 HPSocket 版本号(4 个字节分别为:主版本号,子版本号,修正版本号,构建编号)
  396. DWORD GetHPSocketVersion();
  397. /* 获取错误描述文本 */
  398. LPCTSTR GetSocketErrorDesc(EnSocketError enCode);
  399. /* IPv4 字符串地址转换为整数 */
  400. ULONG GetIPv4InAddr(LPCTSTR lpszAddress);
  401. /* 检查字符串是否符合 IP 地址格式 */
  402. BOOL IsIPAddress(LPCTSTR lpszAddress);
  403. /* 通过主机名获取 IP 地址 */
  404. BOOL GetIPAddress(LPCTSTR lpszHost, __out LPTSTR lpszIP, __inout int& iIPLenth);
  405. /* 通过主机名获取最优的 IP 地址 */
  406. BOOL GetOptimalIPByHostName(LPCTSTR lpszHost, __out IN_ADDR& addr);
  407. /* 获取 IN_ADDR 结构的 IP 地址 */
  408. BOOL IN_ADDR_2_IP(const IN_ADDR& addr, __out LPTSTR lpszAddress, __inout int& iAddressLen);
  409. /* 把 SOCKADDR_IN 结构转换为地址数据 */
  410. BOOL sockaddr_IN_2_A(const SOCKADDR_IN& addr, __out ADDRESS_FAMILY& usFamily, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort);
  411. /* 把地址数据转换为 SOCKADDR_IN 结构 */
  412. BOOL sockaddr_A_2_IN(ADDRESS_FAMILY usFamily, LPCTSTR lpszAddress, USHORT usPort, __out SOCKADDR_IN& addr);
  413. /* 获取 Socket 的本地或远程地址信息 */
  414. BOOL GetSocketAddress(SOCKET socket, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort, BOOL bLocal = TRUE);
  415. /* 获取 Socket 的本地地址信息 */
  416. BOOL GetSocketLocalAddress(SOCKET socket, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort);
  417. /* 获取 Socket 的远程地址信息 */
  418. BOOL GetSocketRemoteAddress(SOCKET socket, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort);
  419. /* 64 位网络字节序转主机字节序 */
  420. ULONGLONG NToH64(ULONGLONG value);
  421. /* 64 位主机字节序转网络字节序 */
  422. ULONGLONG HToN64(ULONGLONG value);
  423. /* 获取 Socket 的某个扩展函数的指针 */
  424. PVOID GetExtensionFuncPtr (SOCKET sock, GUID guid);
  425. /* 获取 AcceptEx 扩展函数指针 */
  426. LPFN_ACCEPTEX Get_AcceptEx_FuncPtr (SOCKET sock);
  427. /* 获取 GetAcceptExSockaddrs 扩展函数指针 */
  428. LPFN_GETACCEPTEXSOCKADDRS Get_GetAcceptExSockaddrs_FuncPtr(SOCKET sock);
  429. /* 获取 ConnectEx 扩展函数指针 */
  430. LPFN_CONNECTEX Get_ConnectEx_FuncPtr (SOCKET sock);
  431. /* 获取 TransmitFile 扩展函数指针 */
  432. LPFN_TRANSMITFILE Get_TransmitFile_FuncPtr (SOCKET sock);
  433. /* 获取 DisconnectEx 扩展函数指针 */
  434. LPFN_DISCONNECTEX Get_DisconnectEx_FuncPtr (SOCKET sock);
  435. HRESULT ReadSmallFile(LPCTSTR lpszFileName, CAtlFile& file, CAtlFileMapping<>& fmap, DWORD dwMaxFileSize = MAX_SMALL_FILE_SIZE);
  436. HRESULT MakeSmallFilePackage(LPCTSTR lpszFileName, CAtlFile& file, CAtlFileMapping<>& fmap, WSABUF szBuf[3], const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr);
  437. /************************************************************************
  438. 名称:IOCP 指令投递帮助方法
  439. 描述:简化 IOCP 指令投递
  440. ************************************************************************/
  441. /* IOCP 命令 */
  442. enum EnIocpCommand
  443. {
  444. IOCP_CMD_EXIT = 0x00000000, // 退出程序
  445. IOCP_CMD_ACCEPT = 0xFFFFFFF1, // 接受连接
  446. IOCP_CMD_DISCONNECT = 0xFFFFFFF2, // 断开连接
  447. IOCP_CMD_SEND = 0xFFFFFFF3 // 发送数据
  448. };
  449. /* IOCP 命令处理动作 */
  450. enum EnIocpAction
  451. {
  452. IOCP_ACT_GOON = 0, // 继续执行
  453. IOCP_ACT_CONTINUE = 1, // 重新执行
  454. IOCP_ACT_BREAK = 2 // 中断执行
  455. };
  456. BOOL PostIocpCommand(HANDLE hIOCP, EnIocpCommand enCmd, ULONG_PTR ulParam);
  457. BOOL PostIocpExit(HANDLE hIOCP);
  458. BOOL PostIocpAccept(HANDLE hIOCP);
  459. BOOL PostIocpDisconnect(HANDLE hIOCP, CONNID dwConnID);
  460. BOOL PostIocpSend(HANDLE hIOCP, CONNID dwConnID);
  461. BOOL PostIocpClose(HANDLE hIOCP, CONNID dwConnID, int iErrorCode);
  462. /************************************************************************
  463. 名称:setsockopt() 帮助方法
  464. 描述:简化常用的 setsockopt() 调用
  465. ************************************************************************/
  466. int SSO_SetSocketOption (SOCKET sock, int level, int name, LPVOID val, int len);
  467. int SSO_GetSocketOption (SOCKET sock, int level, int name, LPVOID val, int* len);
  468. int SSO_IoctlSocket (SOCKET sock, long cmd, u_long* arg);
  469. int SSO_WSAIoctl (SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned);
  470. int SSO_UpdateAcceptContext (SOCKET soClient, SOCKET soBind);
  471. int SSO_UpdateConnectContext(SOCKET soClient, int iOption);
  472. int SSO_NoDelay (SOCKET sock, BOOL bNoDelay = TRUE);
  473. int SSO_DontLinger (SOCKET sock, BOOL bDont = TRUE);
  474. int SSO_Linger (SOCKET sock, USHORT l_onoff, USHORT l_linger);
  475. int SSO_KeepAlive (SOCKET sock, BOOL bKeepAlive = TRUE);
  476. int SSO_KeepAliveVals (SOCKET sock, u_long onoff, u_long time, u_long interval);
  477. int SSO_RecvBuffSize (SOCKET sock, int size);
  478. int SSO_SendBuffSize (SOCKET sock, int size);
  479. int SSO_ReuseAddress (SOCKET sock, BOOL bReuse = TRUE);
  480. int SSO_UDP_ConnReset (SOCKET sock, BOOL bNewBehavior = TRUE);
  481. /************************************************************************
  482. 名称:Socket 操作方法
  483. 描述:Socket 操作包装方法
  484. ************************************************************************/
  485. /* 检测 IOCP 操作返回值:NO_ERROR 则返回 TRUE */
  486. #define IOCP_NO_ERROR(result) (result == NO_ERROR)
  487. /* 检测 IOCP 操作返回值:WSA_IO_PENDING 则返回 TRUE */
  488. #define IOCP_PENDING(result) (result == WSA_IO_PENDING)
  489. /* 检测 IOCP 操作返回值:NO_ERROR 或 WSA_IO_PENDING 则返回 TRUE */
  490. #define IOCP_SUCCESS(result) (IOCP_NO_ERROR(result) || IOCP_PENDING(result))
  491. /* 生成 Connection ID */
  492. CONNID GenerateConnectionID ();
  493. /* 关闭 Socket */
  494. int ManualCloseSocket (SOCKET sock, int iShutdownFlag = 0xFF, BOOL bGraceful = TRUE, BOOL bReuseAddress = FALSE);
  495. /* 投递 AccceptEx(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  496. int PostAccept (LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj);
  497. /* 投递 AccceptEx() */
  498. int PostAcceptNotCheck (LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj);
  499. /* 投递 ConnectEx(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  500. int PostConnect (LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, SOCKADDR_IN& soAddrIN, TBufferObj* pBufferObj);
  501. /* 投递 ConnectEx() */
  502. int PostConnectNotCheck (LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, SOCKADDR_IN& soAddrIN, TBufferObj* pBufferObj);
  503. /* 投递 WSASend(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  504. int PostSend (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  505. /* 投递 WSASend() */
  506. int PostSendNotCheck (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  507. /* 投递 WSARecv() ,并把 WSA_IO_PENDING 转换为 NO_ERROR*/
  508. int PostReceive (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  509. /* 投递 WSARecv() */
  510. int PostReceiveNotCheck (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  511. /* 投递 WSASendTo() ,并把 WSA_IO_PENDING 转换为 NO_ERROR*/
  512. int PostSendTo (SOCKET sock, TUdpBufferObj* pBufferObj);
  513. /* 投递 WSASendTo() */
  514. int PostSendToNotCheck (SOCKET sock, TUdpBufferObj* pBufferObj);
  515. /* 投递 WSARecvFrom() ,并把 WSA_IO_PENDING 转换为 NO_ERROR*/
  516. int PostReceiveFrom (SOCKET sock, TUdpBufferObj* pBufferObj);
  517. /* 投递 WSARecvFrom() */
  518. int PostReceiveFromNotCheck (SOCKET sock, TUdpBufferObj* pBufferObj);