工具项目

SocketHelper.h 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Author : Bruce Liang
  5. * Website : http://www.jessma.org
  6. * Project : https://github.com/ldcsaa
  7. * Blog : http://www.cnblogs.com/ldcsaa
  8. * Wiki : http://www.oschina.net/p/hp-socket
  9. * QQ Group : 75375912, 44636872
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. */
  23. #pragma once
  24. #include <ws2tcpip.h>
  25. #include <mswsock.h>
  26. #include <malloc.h>
  27. #include <atlfile.h>
  28. #include "SocketInterface.h"
  29. #include "../Common/Src/WaitFor.h"
  30. #include "../Common/Src/SysHelper.h"
  31. #include "../Common/Src/FuncHelper.h"
  32. #include "../Common/Src/BufferPool.h"
  33. #include "../Common/Src/RingBuffer.h"
  34. /************************************************************************
  35. 名称:全局常量
  36. 描述:声明组件的公共全局常量
  37. ************************************************************************/
  38. /* IOCP Socket 缓冲区最小值 */
  39. #define MIN_SOCKET_BUFFER_SIZE 88
  40. /* 小文件最大字节数 */
  41. #define MAX_SMALL_FILE_SIZE 0x3FFFFF
  42. /* 最大连接时长 */
  43. #define MAX_CONNECTION_PERIOD (MAXLONG / 2)
  44. /* IOCP 处理接收事件时最大额外读取次数 */
  45. #define MAX_IOCP_CONTINUE_RECEIVE 30
  46. /* Server/Agent 默认最大连接数 */
  47. #define DEFAULT_MAX_CONNECTION_COUNT 10000
  48. /* Server/Agent 默认 Socket 缓存对象锁定时间 */
  49. #define DEFAULT_FREE_SOCKETOBJ_LOCK_TIME (10 * 1000)
  50. /* Server/Agent 默认 Socket 缓存池大小 */
  51. #define DEFAULT_FREE_SOCKETOBJ_POOL 150
  52. /* Server/Agent 默认 Socket 缓存池回收阀值 */
  53. #define DEFAULT_FREE_SOCKETOBJ_HOLD 600
  54. /* Server/Agent 默认内存块缓存池大小 */
  55. #define DEFAULT_FREE_BUFFEROBJ_POOL 300
  56. /* Server/Agent 默认内存块缓存池回收阀值 */
  57. #define DEFAULT_FREE_BUFFEROBJ_HOLD 1200
  58. /* Client 默认内存块缓存池大小 */
  59. #define DEFAULT_CLIENT_FREE_BUFFER_POOL_SIZE 10
  60. /* Client 默认内存块缓存池回收阀值 */
  61. #define DEFAULT_CLIENT_FREE_BUFFER_POOL_HOLD 40
  62. /* IPv4 默认绑定地址 */
  63. #define DEFAULT_IPV4_BIND_ADDRESS _T("0.0.0.0")
  64. /* IPv6 默认绑定地址 */
  65. #define DEFAULT_IPV6_BIND_ADDRESS _T("::")
  66. /* TCP 默认通信数据缓冲区大小 */
  67. #define DEFAULT_TCP_SOCKET_BUFFER_SIZE DEFAULT_BUFFER_SIZE
  68. /* TCP 默认心跳包间隔 */
  69. #define DEFALUT_TCP_KEEPALIVE_TIME (30 * 1000)
  70. /* TCP 默认心跳确认包检测间隔 */
  71. #define DEFALUT_TCP_KEEPALIVE_INTERVAL (10 * 1000)
  72. /* TCP Server 默认 Listen 队列大小 */
  73. #define DEFAULT_TCP_SERVER_SOCKET_LISTEN_QUEUE SOMAXCONN
  74. /* TCP Server 默认预投递 Accept 数量 */
  75. #define DEFAULT_TCP_SERVER_ACCEPT_SOCKET_COUNT 300
  76. /* UDP 默认数据报文最大长度 */
  77. #define DEFAULT_UDP_MAX_DATAGRAM_SIZE 1472
  78. /* UDP 默认 Receive 预投递数量 */
  79. #define DEFAULT_UDP_POST_RECEIVE_COUNT 300
  80. /* UDP 默认监测包尝试次数 */
  81. #define DEFAULT_UDP_DETECT_ATTEMPTS 3
  82. /* UDP 默认监测包发送间隔 */
  83. #define DEFAULT_UDP_DETECT_INTERVAL 30
  84. /* TCP Pack 包长度位数 */
  85. #define TCP_PACK_LENGTH_BITS 22
  86. /* TCP Pack 包长度掩码 */
  87. #define TCP_PACK_LENGTH_MASK 0x3FFFFF
  88. /* TCP Pack 包最大长度硬限制 */
  89. #define TCP_PACK_MAX_SIZE_LIMIT 0x3FFFFF
  90. /* TCP Pack 包默认最大长度 */
  91. #define TCP_PACK_DEFAULT_MAX_SIZE 0x040000
  92. /* TCP Pack 包头标识值硬限制 */
  93. #define TCP_PACK_HEADER_FLAG_LIMIT 0x0003FF
  94. /* TCP Pack 包头默认标识值 */
  95. #define TCP_PACK_DEFAULT_HEADER_FLAG 0x000000
  96. #define PORT_SEPARATOR_CHAR ':'
  97. #define IPV6_ADDR_BEGIN_CHAR '['
  98. #define IPV6_ADDR_END_CHAR ']'
  99. #define IPV4_ADDR_SEPARATOR_CHAR '.'
  100. #define IPV6_ADDR_SEPARATOR_CHAR ':'
  101. #define IPV6_ZONE_INDEX_CHAR '%'
  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() const {return m_iResult;}
  122. BOOL IsValid() const {return m_iResult == 0;}
  123. private:
  124. int m_iResult;
  125. };
  126. typedef struct hp_addr
  127. {
  128. ADDRESS_FAMILY family;
  129. union
  130. {
  131. ULONG_PTR addr;
  132. IN_ADDR addr4;
  133. IN6_ADDR addr6;
  134. };
  135. static const hp_addr ANY_ADDR4;
  136. static const hp_addr ANY_ADDR6;
  137. inline int AddrSize() const
  138. {
  139. return AddrSize(family);
  140. }
  141. inline static int AddrSize(ADDRESS_FAMILY f)
  142. {
  143. if(f == AF_INET)
  144. return sizeof(IN_ADDR);
  145. return sizeof(IN6_ADDR);
  146. }
  147. inline static const hp_addr& AnyAddr(ADDRESS_FAMILY f)
  148. {
  149. if(f == AF_INET)
  150. return ANY_ADDR4;
  151. return ANY_ADDR6;
  152. }
  153. inline const ULONG_PTR* Addr() const {return &addr;}
  154. inline ULONG_PTR* Addr() {return &addr;}
  155. inline BOOL IsIPv4() const {return family == AF_INET;}
  156. inline BOOL IsIPv6() const {return family == AF_INET6;}
  157. inline BOOL IsSpecified() const {return IsIPv4() || IsIPv6();}
  158. inline void ZeroAddr() {::ZeroMemory(&addr6, sizeof(addr6));}
  159. inline void Reset() {::ZeroMemory(this, sizeof(*this));}
  160. inline hp_addr& Copy(hp_addr& other) const
  161. {
  162. if(this != &other)
  163. memcpy(&other, this, offsetof(hp_addr, addr) + AddrSize());
  164. return other;
  165. }
  166. hp_addr(ADDRESS_FAMILY f = AF_UNSPEC, BOOL bZeroAddr = FALSE)
  167. {
  168. family = f;
  169. if(bZeroAddr) ZeroAddr();
  170. }
  171. } HP_ADDR, *HP_PADDR;
  172. typedef struct hp_sockaddr
  173. {
  174. union
  175. {
  176. ADDRESS_FAMILY family;
  177. SOCKADDR addr;
  178. SOCKADDR_IN addr4;
  179. SOCKADDR_IN6 addr6;
  180. };
  181. inline int AddrSize() const
  182. {
  183. return AddrSize(family);
  184. }
  185. inline static int AddrSize(ADDRESS_FAMILY f)
  186. {
  187. if(f == AF_INET)
  188. return sizeof(SOCKADDR_IN);
  189. return sizeof(SOCKADDR_IN6);
  190. }
  191. inline static const hp_sockaddr& AnyAddr(ADDRESS_FAMILY f)
  192. {
  193. static const hp_sockaddr s_any_addr4(AF_INET, TRUE);
  194. static const hp_sockaddr s_any_addr6(AF_INET6, TRUE);
  195. if(f == AF_INET)
  196. return s_any_addr4;
  197. return s_any_addr6;
  198. }
  199. inline static int AddrMinStrLength(ADDRESS_FAMILY f)
  200. {
  201. if(f == AF_INET)
  202. return 16;
  203. return 46;
  204. }
  205. inline BOOL IsIPv4() const {return family == AF_INET;}
  206. inline BOOL IsIPv6() const {return family == AF_INET6;}
  207. inline BOOL IsSpecified() const {return IsIPv4() || IsIPv6();}
  208. inline USHORT Port() const {return ntohs(addr4.sin_port);}
  209. inline void SetPort(USHORT usPort) {addr4.sin_port = htons(usPort);}
  210. inline void* SinAddr() const {return IsIPv4() ? (void*)&addr4.sin_addr : (void*)&addr6.sin6_addr;}
  211. inline void* SinAddr() {return IsIPv4() ? (void*)&addr4.sin_addr : (void*)&addr6.sin6_addr;}
  212. inline const SOCKADDR* Addr() const {return &addr;}
  213. inline SOCKADDR* Addr() {return &addr;}
  214. inline void ZeroAddr() {::ZeroMemory(((char*)this) + sizeof(family), sizeof(*this) - sizeof(family));}
  215. inline void Reset() {::ZeroMemory(this, sizeof(*this));}
  216. inline hp_sockaddr& Copy(hp_sockaddr& other) const
  217. {
  218. if(this != &other)
  219. memcpy(&other, this, AddrSize());
  220. return other;
  221. }
  222. size_t Hash() const
  223. {
  224. ASSERT(IsSpecified());
  225. if(IsIPv4())
  226. return ((addr4.sin_family << 16) | addr4.sin_port) ^ addr4.sin_addr.s_addr;
  227. else
  228. {
  229. ULONG* p = (ULONG*)(((char*)this) + offsetof(SOCKADDR_IN6, sin6_addr));
  230. return ((addr6.sin6_family << 16) | addr6.sin6_port) ^ addr6.sin6_flowinfo ^ p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
  231. }
  232. }
  233. bool EqualTo(const hp_sockaddr& other) const
  234. {
  235. ASSERT(IsSpecified() && other.IsSpecified());
  236. if(IsIPv4())
  237. return memcmp(this, &other, offsetof(SOCKADDR_IN, sin_zero)) == 0;
  238. else
  239. return memcmp(this, &other, sizeof(addr6)) == 0;
  240. }
  241. hp_sockaddr(ADDRESS_FAMILY f = AF_UNSPEC, BOOL bZeroAddr = FALSE)
  242. {
  243. family = f;
  244. if(bZeroAddr) ZeroAddr();
  245. }
  246. } HP_SOCKADDR, *HP_PSOCKADDR;
  247. /* Server 组件和 Agent 组件内部使用的事件处理结果常量 */
  248. // 连接已关闭
  249. #define HR_CLOSED 0xFF
  250. /* 关闭连接标识 */
  251. enum EnSocketCloseFlag
  252. {
  253. SCF_NONE = 0, // 不触发事件
  254. SCF_CLOSE = 1, // 触发 正常关闭 OnClose 事件
  255. SCF_ERROR = 2 // 触发 异常关闭 OnClose 事件
  256. };
  257. /* 数据缓冲区基础结构 */
  258. template<class T> struct TBufferObjBase
  259. {
  260. WSAOVERLAPPED ov;
  261. EnSocketOperation operation;
  262. WSABUF buff;
  263. int capacity;
  264. CPrivateHeap& heap;
  265. volatile LONG sndCounter;
  266. T* next;
  267. T* last;
  268. static T* Construct(CPrivateHeap& heap, DWORD dwCapacity)
  269. {
  270. T* pBufferObj = (T*)heap.Alloc(sizeof(T) + dwCapacity);
  271. ASSERT(pBufferObj);
  272. ZeroMemory(pBufferObj, sizeof(T));
  273. pBufferObj->TBufferObjBase::TBufferObjBase(heap, dwCapacity);
  274. pBufferObj->buff.buf = ((char*)pBufferObj) + sizeof(T);
  275. return pBufferObj;
  276. }
  277. static void Destruct(T* pBufferObj)
  278. {
  279. ASSERT(pBufferObj);
  280. pBufferObj->heap.Free(pBufferObj);
  281. }
  282. void ResetSendCounter()
  283. {
  284. sndCounter = 2;
  285. }
  286. LONG ReleaseSendCounter()
  287. {
  288. return ::InterlockedDecrement(&sndCounter);
  289. }
  290. TBufferObjBase(CPrivateHeap& hp, DWORD dwCapacity)
  291. : heap(hp)
  292. , capacity((int)dwCapacity)
  293. {
  294. ASSERT(capacity > 0);
  295. }
  296. int Cat(const BYTE* pData, int length)
  297. {
  298. ASSERT(pData != nullptr && length > 0);
  299. int cat = min(Remain(), length);
  300. if(cat > 0)
  301. {
  302. memcpy(buff.buf + buff.len, pData, cat);
  303. buff.len += cat;
  304. }
  305. return cat;
  306. }
  307. void Reset() {buff.len = 0;}
  308. int Remain() {return capacity - buff.len;}
  309. BOOL IsFull() {return Remain() == 0;}
  310. };
  311. /* 数据缓冲区结构 */
  312. struct TBufferObj : public TBufferObjBase<TBufferObj>
  313. {
  314. SOCKET client;
  315. };
  316. /* UDP 数据缓冲区结构 */
  317. struct TUdpBufferObj : public TBufferObjBase<TUdpBufferObj>
  318. {
  319. HP_SOCKADDR remoteAddr;
  320. int addrLen;
  321. };
  322. /* 数据缓冲区链表模板 */
  323. template<class T> struct TBufferObjListT : public TSimpleList<T>
  324. {
  325. public:
  326. int Cat(const BYTE* pData, int length)
  327. {
  328. ASSERT(pData != nullptr && length > 0);
  329. int remain = length;
  330. while(remain > 0)
  331. {
  332. T* pItem = Back();
  333. if(pItem == nullptr || pItem->IsFull())
  334. pItem = PushBack(bfPool.PickFreeItem());
  335. int cat = pItem->Cat(pData, remain);
  336. pData += cat;
  337. remain -= cat;
  338. }
  339. return length;
  340. }
  341. T* PushTail(const BYTE* pData, int length)
  342. {
  343. ASSERT(pData != nullptr && length > 0 && length <= (int)bfPool.GetItemCapacity());
  344. T* pItem = PushBack(bfPool.PickFreeItem());
  345. pItem->Cat(pData, length);
  346. return pItem;
  347. }
  348. void Release()
  349. {
  350. bfPool.PutFreeItem(*this);
  351. }
  352. public:
  353. TBufferObjListT(CNodePoolT<T>& pool) : bfPool(pool)
  354. {
  355. }
  356. private:
  357. CNodePoolT<T>& bfPool;
  358. };
  359. /* 数据缓冲区对象池 */
  360. typedef CNodePoolT<TBufferObj> CBufferObjPool;
  361. /* UDP 数据缓冲区对象池 */
  362. typedef CNodePoolT<TUdpBufferObj> CUdpBufferObjPool;
  363. /* 数据缓冲区链表模板 */
  364. typedef TBufferObjListT<TBufferObj> TBufferObjList;
  365. /* UDP 数据缓冲区链表模板 */
  366. typedef TBufferObjListT<TUdpBufferObj> TUdpBufferObjList;
  367. /* 数据缓冲区结构链表 */
  368. typedef CRingPool<TBufferObj> TBufferObjPtrList;
  369. /* Udp 数据缓冲区结构链表 */
  370. typedef CRingPool<TUdpBufferObj> TUdpBufferObjPtrList;
  371. /* Socket 缓冲区基础结构 */
  372. struct TSocketObjBase
  373. {
  374. static const long DEF_SNDBUFF_SIZE = 8192;
  375. CONNID connID;
  376. BOOL connected;
  377. HP_SOCKADDR remoteAddr;
  378. PVOID extra;
  379. PVOID reserved;
  380. PVOID reserved2;
  381. BOOL valid;
  382. union
  383. {
  384. DWORD freeTime;
  385. DWORD connTime;
  386. };
  387. DWORD activeTime;
  388. CCriSec csSend;
  389. long sndBuffSize;
  390. volatile BOOL smooth;
  391. volatile long pending;
  392. volatile long sndCount;
  393. volatile BOOL paused;
  394. volatile BOOL recving;
  395. CReentrantSpinGuard csRecv;
  396. static BOOL IsExist(TSocketObjBase* pSocketObj)
  397. {return pSocketObj != nullptr;}
  398. static BOOL IsValid(TSocketObjBase* pSocketObj)
  399. {return pSocketObj != nullptr && pSocketObj->valid;}
  400. static void Invalid(TSocketObjBase* pSocketObj)
  401. {ASSERT(IsExist(pSocketObj)); pSocketObj->valid = FALSE;}
  402. static void Release(TSocketObjBase* pSocketObj)
  403. {ASSERT(IsExist(pSocketObj)); pSocketObj->freeTime = ::TimeGetTime();}
  404. long Pending() {return pending;}
  405. BOOL IsPending() {return pending > 0;}
  406. BOOL IsCanSend() {return sndCount <= sndBuffSize;}
  407. BOOL IsSmooth() {return smooth;}
  408. void TurnOnSmooth() {smooth = TRUE;}
  409. BOOL TurnOffSmooth()
  410. {return ::InterlockedCompareExchange((volatile long*)&smooth, FALSE, TRUE) == TRUE;}
  411. BOOL ResetSndBuffSize(SOCKET socket)
  412. {
  413. int len = (int)(sizeof(sndBuffSize));
  414. return getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (CHAR*)&sndBuffSize, &len) != 0;
  415. }
  416. BOOL HasConnected()
  417. {
  418. return connected;
  419. }
  420. void SetConnected(BOOL bConnected = TRUE)
  421. {
  422. connected = bConnected;
  423. }
  424. void Reset(CONNID dwConnID)
  425. {
  426. connID = dwConnID;
  427. connected = FALSE;
  428. valid = TRUE;
  429. smooth = TRUE;
  430. paused = FALSE;
  431. recving = FALSE;
  432. pending = 0;
  433. sndCount = 0;
  434. sndBuffSize = DEF_SNDBUFF_SIZE;
  435. extra = nullptr;
  436. reserved = nullptr;
  437. reserved2 = nullptr;
  438. }
  439. };
  440. /* 数据缓冲区结构 */
  441. struct TSocketObj : public TSocketObjBase
  442. {
  443. SOCKET socket;
  444. CStringA host;
  445. TBufferObjList sndBuff;
  446. TSocketObj(CBufferObjPool& bfPool)
  447. : sndBuff(bfPool)
  448. {
  449. }
  450. static void Release(TSocketObj* pSocketObj)
  451. {
  452. __super::Release(pSocketObj);
  453. pSocketObj->sndBuff.Release();
  454. }
  455. void Reset(CONNID dwConnID, SOCKET soClient)
  456. {
  457. __super::Reset(dwConnID);
  458. host.Empty();
  459. socket = soClient;
  460. }
  461. BOOL GetRemoteHost(LPCSTR* lpszHost, USHORT* pusPort = nullptr)
  462. {
  463. *lpszHost = host;
  464. if(pusPort)
  465. *pusPort = remoteAddr.Port();
  466. return (*lpszHost != nullptr && (*lpszHost)[0] != 0);
  467. }
  468. };
  469. /* UDP 数据缓冲区结构 */
  470. struct TUdpSocketObj : public TSocketObjBase
  471. {
  472. TUdpBufferObjList sndBuff;
  473. volatile DWORD detectFails;
  474. TUdpSocketObj(CUdpBufferObjPool& bfPool)
  475. : sndBuff(bfPool)
  476. {
  477. }
  478. static void Release(TUdpSocketObj* pSocketObj)
  479. {
  480. __super::Release(pSocketObj);
  481. pSocketObj->sndBuff.Release();
  482. }
  483. void Reset(CONNID dwConnID)
  484. {
  485. __super::Reset(dwConnID);
  486. detectFails = 0;
  487. }
  488. };
  489. /* 有效 TSocketObj 缓存 */
  490. typedef CRingCache2<TSocketObj, CONNID, true> TSocketObjPtrPool;
  491. /* 失效 TSocketObj 缓存 */
  492. typedef CRingPool<TSocketObj> TSocketObjPtrList;
  493. /* 失效 TSocketObj 垃圾回收结构链表 */
  494. typedef CCASQueue<TSocketObj> TSocketObjPtrQueue;
  495. /* 有效 TUdpSocketObj 缓存 */
  496. typedef CRingCache2<TUdpSocketObj, CONNID, true> TUdpSocketObjPtrPool;
  497. /* 失效 TUdpSocketObj 缓存 */
  498. typedef CRingPool<TUdpSocketObj> TUdpSocketObjPtrList;
  499. /* 失效 TUdpSocketObj 垃圾回收结构链表 */
  500. typedef CCASQueue<TUdpSocketObj> TUdpSocketObjPtrQueue;
  501. /* HP_SOCKADDR 比较器 */
  502. struct hp_sockaddr_func
  503. {
  504. struct hash
  505. {
  506. size_t operator() (const HP_SOCKADDR* pA) const
  507. {
  508. return pA->Hash();
  509. }
  510. };
  511. struct equal_to
  512. {
  513. bool operator () (const HP_SOCKADDR* pA, const HP_SOCKADDR* pB) const
  514. {
  515. return pA->EqualTo(*pB);
  516. }
  517. };
  518. };
  519. /* 地址-连接 ID 哈希表 */
  520. typedef unordered_map<const HP_SOCKADDR*, CONNID, hp_sockaddr_func::hash, hp_sockaddr_func::equal_to>
  521. TSockAddrMap;
  522. /* 地址-连接 ID 哈希表迭代器 */
  523. typedef TSockAddrMap::iterator TSockAddrMapI;
  524. /* 地址-连接 ID 哈希表 const 迭代器 */
  525. typedef TSockAddrMap::const_iterator TSockAddrMapCI;
  526. /* IClient 组件关闭上下文 */
  527. struct TClientCloseContext
  528. {
  529. BOOL bFireOnClose;
  530. EnSocketOperation enOperation;
  531. int iErrorCode;
  532. TClientCloseContext(BOOL bFire = TRUE, EnSocketOperation enOp = SO_CLOSE, int iCode = SE_OK)
  533. {
  534. Reset(bFire, enOp, iCode);
  535. }
  536. void Reset(BOOL bFire = TRUE, EnSocketOperation enOp = SO_CLOSE, int iCode = SE_OK)
  537. {
  538. bFireOnClose = bFire;
  539. enOperation = enOp;
  540. iErrorCode = iCode;
  541. }
  542. };
  543. /*****************************************************************************************************/
  544. /******************************************** 公共帮助方法 ********************************************/
  545. /*****************************************************************************************************/
  546. /* 获取错误描述文本 */
  547. LPCTSTR GetSocketErrorDesc(EnSocketError enCode);
  548. /* 确定地址簇 */
  549. ADDRESS_FAMILY DetermineAddrFamily(LPCTSTR lpszAddress);
  550. /* 地址字符串地址转换为 HP_ADDR */
  551. BOOL GetInAddr(LPCTSTR lpszAddress, __out HP_ADDR& addr);
  552. /* 地址字符串地址转换为 HP_SOCKADDR */
  553. BOOL GetSockAddr(LPCTSTR lpszAddress, USHORT usPort, __inout HP_SOCKADDR& addr);
  554. /* 检查字符串是否符合 IP 地址格式 */
  555. BOOL IsIPAddress(LPCTSTR lpszAddress, __out EnIPAddrType* penType = nullptr);
  556. /* 通过主机名获取 IP 地址 */
  557. BOOL GetIPAddress(LPCTSTR lpszHost, __out LPTSTR lpszIP, __inout int& iIPLenth, __out EnIPAddrType& enType);
  558. /* 通过主机名获取 HP_SOCKADDR */
  559. BOOL GetSockAddrByHostName(LPCTSTR lpszHost, USHORT usPort, __out HP_SOCKADDR& addr);
  560. /* 通过主机名获取 HP_SOCKADDR */
  561. BOOL GetSockAddrByHostNameDirectly(LPCTSTR lpszHost, USHORT usPort, HP_SOCKADDR &addr);
  562. /* 枚举主机 IP 地址 */
  563. BOOL EnumHostIPAddresses(LPCTSTR lpszHost, EnIPAddrType enType, __out LPTIPAddr** lpppIPAddr, __out int& iIPAddrCount);
  564. /* 填充 LPTIPAddr* */
  565. BOOL RetrieveSockAddrIPAddresses(const vector<HP_PSOCKADDR>& vt, __out LPTIPAddr** lpppIPAddr, __out int& iIPAddrCount);
  566. /* 释放 LPTIPAddr* */
  567. BOOL FreeHostIPAddresses(LPTIPAddr* lppIPAddr);
  568. /* 把 HP_SOCKADDR 结构转换为地址字符串 */
  569. BOOL sockaddr_IN_2_A(const HP_SOCKADDR& addr, __out ADDRESS_FAMILY& usFamily, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort);
  570. /* 把地址字符串转换为 HP_SOCKADDR 结构 */
  571. BOOL sockaddr_A_2_IN(LPCTSTR lpszAddress, USHORT usPort, __out HP_SOCKADDR& addr);
  572. /* 获取 Socket 的本地或远程地址信息 */
  573. BOOL GetSocketAddress(SOCKET socket, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort, BOOL bLocal = TRUE);
  574. /* 获取 Socket 的本地地址信息 */
  575. BOOL GetSocketLocalAddress(SOCKET socket, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort);
  576. /* 获取 Socket 的远程地址信息 */
  577. BOOL GetSocketRemoteAddress(SOCKET socket, __out LPTSTR lpszAddress, __inout int& iAddressLen, __out USHORT& usPort);
  578. /* 64 位网络字节序转主机字节序 */
  579. ULONGLONG NToH64(ULONGLONG value);
  580. /* 64 位主机字节序转网络字节序 */
  581. ULONGLONG HToN64(ULONGLONG value);
  582. /* 获取 Socket 的某个扩展函数的指针 */
  583. PVOID GetExtensionFuncPtr (SOCKET sock, GUID guid);
  584. /* 获取 AcceptEx 扩展函数指针 */
  585. LPFN_ACCEPTEX Get_AcceptEx_FuncPtr (SOCKET sock);
  586. /* 获取 GetAcceptExSockaddrs 扩展函数指针 */
  587. LPFN_GETACCEPTEXSOCKADDRS Get_GetAcceptExSockaddrs_FuncPtr(SOCKET sock);
  588. /* 获取 ConnectEx 扩展函数指针 */
  589. LPFN_CONNECTEX Get_ConnectEx_FuncPtr (SOCKET sock);
  590. /* 获取 TransmitFile 扩展函数指针 */
  591. LPFN_TRANSMITFILE Get_TransmitFile_FuncPtr (SOCKET sock);
  592. /* 获取 DisconnectEx 扩展函数指针 */
  593. LPFN_DISCONNECTEX Get_DisconnectEx_FuncPtr (SOCKET sock);
  594. HRESULT ReadSmallFile(LPCTSTR lpszFileName, CAtlFile& file, CAtlFileMapping<>& fmap, DWORD dwMaxFileSize = MAX_SMALL_FILE_SIZE);
  595. HRESULT MakeSmallFilePackage(LPCTSTR lpszFileName, CAtlFile& file, CAtlFileMapping<>& fmap, WSABUF szBuf[3], const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr);
  596. /************************************************************************
  597. 名称:IOCP 指令投递帮助方法
  598. 描述:简化 IOCP 指令投递
  599. ************************************************************************/
  600. /* IOCP 命令 */
  601. enum EnIocpCommand
  602. {
  603. IOCP_CMD_EXIT = 0x00000000, // 退出程序
  604. IOCP_CMD_ACCEPT = 0xFFFFFFF1, // 接受连接
  605. IOCP_CMD_DISCONNECT = 0xFFFFFFF2, // 断开连接
  606. IOCP_CMD_SEND = 0xFFFFFFF3 // 发送数据
  607. };
  608. /* IOCP 命令处理动作 */
  609. enum EnIocpAction
  610. {
  611. IOCP_ACT_GOON = 0, // 继续执行
  612. IOCP_ACT_CONTINUE = 1, // 重新执行
  613. IOCP_ACT_BREAK = 2 // 中断执行
  614. };
  615. BOOL PostIocpCommand(HANDLE hIOCP, EnIocpCommand enCmd, ULONG_PTR ulParam);
  616. BOOL PostIocpExit(HANDLE hIOCP);
  617. BOOL PostIocpAccept(HANDLE hIOCP);
  618. BOOL PostIocpDisconnect(HANDLE hIOCP, CONNID dwConnID);
  619. BOOL PostIocpSend(HANDLE hIOCP, CONNID dwConnID);
  620. BOOL PostIocpClose(HANDLE hIOCP, CONNID dwConnID, int iErrorCode);
  621. /************************************************************************
  622. 名称:setsockopt() 帮助方法
  623. 描述:简化常用的 setsockopt() 调用
  624. ************************************************************************/
  625. int SSO_SetSocketOption (SOCKET sock, int level, int name, LPVOID val, int len);
  626. int SSO_GetSocketOption (SOCKET sock, int level, int name, LPVOID val, int* len);
  627. int SSO_IoctlSocket (SOCKET sock, long cmd, u_long* arg);
  628. int SSO_WSAIoctl (SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned);
  629. int SSO_UpdateAcceptContext (SOCKET soClient, SOCKET soBind);
  630. int SSO_UpdateConnectContext(SOCKET soClient, int iOption);
  631. int SSO_NoBlock (SOCKET sock, BOOL bNoBlock = TRUE);
  632. int SSO_NoDelay (SOCKET sock, BOOL bNoDelay = TRUE);
  633. int SSO_DontLinger (SOCKET sock, BOOL bDont = TRUE);
  634. int SSO_Linger (SOCKET sock, USHORT l_onoff, USHORT l_linger);
  635. int SSO_KeepAlive (SOCKET sock, BOOL bKeepAlive = TRUE);
  636. int SSO_KeepAliveVals (SOCKET sock, u_long onoff, u_long time, u_long interval);
  637. int SSO_RecvBuffSize (SOCKET sock, int size);
  638. int SSO_SendBuffSize (SOCKET sock, int size);
  639. int SSO_ReuseAddress (SOCKET sock, BOOL bReuse = TRUE);
  640. int SSO_UDP_ConnReset (SOCKET sock, BOOL bNewBehavior = TRUE);
  641. /************************************************************************
  642. 名称:Socket 操作方法
  643. 描述:Socket 操作包装方法
  644. ************************************************************************/
  645. /* 检测 IOCP 操作返回值:NO_ERROR 则返回 TRUE */
  646. #define IOCP_NO_ERROR(result) (result == NO_ERROR)
  647. /* 检测 IOCP 操作返回值:WSA_IO_PENDING 则返回 TRUE */
  648. #define IOCP_PENDING(result) (result == WSA_IO_PENDING)
  649. /* 检测 IOCP 操作返回值:NO_ERROR 或 WSA_IO_PENDING 则返回 TRUE */
  650. #define IOCP_SUCCESS(result) (IOCP_NO_ERROR(result) || IOCP_PENDING(result))
  651. /* 生成 Connection ID */
  652. CONNID GenerateConnectionID ();
  653. /* 关闭 Socket */
  654. int ManualCloseSocket (SOCKET sock, int iShutdownFlag = 0xFF, BOOL bGraceful = TRUE, BOOL bReuseAddress = FALSE);
  655. /* 投递 AccceptEx(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  656. int PostAccept (LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj, ADDRESS_FAMILY usFamily);
  657. /* 投递 AccceptEx() */
  658. int PostAcceptNotCheck (LPFN_ACCEPTEX pfnAcceptEx, SOCKET soListen, SOCKET soClient, TBufferObj* pBufferObj, ADDRESS_FAMILY usFamily);
  659. /* 投递 ConnectEx(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  660. int PostConnect (LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, const HP_SOCKADDR& sockAddr, TBufferObj* pBufferObj);
  661. /* 投递 ConnectEx() */
  662. int PostConnectNotCheck (LPFN_CONNECTEX pfnConnectEx, SOCKET soClient, const HP_SOCKADDR& sockAddr, TBufferObj* pBufferObj);
  663. /* 投递 WSASend(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  664. int PostSend (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  665. /* 投递 WSASend() */
  666. int PostSendNotCheck (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  667. /* 投递 WSARecv(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  668. int PostReceive (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  669. /* 投递 WSARecv() */
  670. int PostReceiveNotCheck (TSocketObj* pSocketObj, TBufferObj* pBufferObj);
  671. /* 投递 WSASendTo(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  672. int PostSendTo (SOCKET sock, TUdpBufferObj* pBufferObj);
  673. /* 投递 WSASendTo() */
  674. int PostSendToNotCheck (SOCKET sock, TUdpBufferObj* pBufferObj);
  675. /* 投递 WSARecvFrom(),并把 WSA_IO_PENDING 转换为 NO_ERROR */
  676. int PostReceiveFrom (SOCKET sock, TUdpBufferObj* pBufferObj);
  677. /* 投递 WSARecvFrom() */
  678. int PostReceiveFromNotCheck (SOCKET sock, TUdpBufferObj* pBufferObj);
  679. /* 执行非阻塞 WSARecv(),并把 WSAEWOULDBLOCK 转换为 NO_ERROR */
  680. int NoBlockReceive(TBufferObj* pBufferObj);
  681. /* 执行非阻塞 WSARecv() */
  682. int NoBlockReceiveNotCheck(TBufferObj* pBufferObj);