复件 SocketHandle.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. ** Copyright 2003-2009, Ernest Laurentin (http://www.ernzo.com/)
  3. **
  4. ** Licensed under the Apache License, Version 2.0 (the "License");
  5. ** you may not use this file except in compliance with the License.
  6. ** You may obtain a copy of the License at
  7. **
  8. ** http://www.apache.org/licenses/LICENSE-2.0
  9. **
  10. ** Unless required by applicable law or agreed to in writing, software
  11. ** distributed under the License is distributed on an "AS IS" BASIS,
  12. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ** See the License for the specific language governing permissions and
  14. ** limitations under the License.
  15. **
  16. ** File: SocketHandle.h
  17. ** Version: 1.4 - IPv6 support
  18. ** 1.3 - Update for Asynchronous mode / Linux port
  19. ** 1.2 - Update interface for TCP remote connection
  20. ** 1.1 - Added multicast support
  21. */
  22. #ifndef SOCKETHANDLE_H
  23. #define SOCKETHANDLE_H
  24. #ifdef WIN32
  25. #include <winsock2.h>
  26. #include <ws2tcpip.h>
  27. #elif BSD_SOCKET
  28. #include "platform.h"
  29. #endif
  30. /**
  31. * @defgroup _SockHandle Socket Communication Classes
  32. * @{
  33. */
  34. /**
  35. * SockAddrIn structure
  36. * Encapsulate SOCKADDR_STORAGE (IPv4: SOCKADDR_IN, IPv6: SOCKADDR_IN6) structures
  37. */
  38. struct SockAddrIn : public sockaddr_storage {
  39. public:
  40. /**
  41. * Default constructor
  42. */
  43. SockAddrIn();
  44. /**
  45. * Copy constructor
  46. * @param sin reference object
  47. */
  48. SockAddrIn(const SockAddrIn& sin);
  49. /**
  50. * Destructor
  51. */
  52. ~SockAddrIn();
  53. /**
  54. * Copy function
  55. * @param sin reference object
  56. * @return reference of 'this' object
  57. */
  58. SockAddrIn& Copy(const SockAddrIn& sin);
  59. /**
  60. * Clear struct
  61. */
  62. void Clear();
  63. /**
  64. * Compare NetworkAddr object
  65. * @param sin reference object
  66. * @return true if equal, otherwise false
  67. */
  68. bool IsEqual(const SockAddrIn& sin) const;
  69. /**
  70. * Check if NULL
  71. * @return true if object is 'NULL' - not valid
  72. */
  73. bool IsNull() const { return IsEqual(NULLAddr); }
  74. /**
  75. * Get Socket address family
  76. * @return Socket address family (IPv4: AF_INET, IPv6: AF_INET6)
  77. */
  78. short GetFamily () const { return ss_family; }
  79. /**
  80. * Get IP address (IPv4)
  81. * @return IPv4 network address in network format
  82. */
  83. ULONG GetIPAddr() const { return ((SOCKADDR_IN*)this)->sin_addr.s_addr; }
  84. /**
  85. * Get Port
  86. * @return Port number in network format
  87. */
  88. short GetPort() const { return ((SOCKADDR_IN*)this)->sin_port; }
  89. /**
  90. * Create from string. Service is service name or port number.
  91. * @param pszAddr Hostname or IP address
  92. * @param pszService Service name or port
  93. * @param nFamily Socket address family (default: AF_INET, AF_INET6)
  94. * @return true if object is now valid
  95. */
  96. bool CreateFrom(LPCTSTR pszAddr, LPCTSTR pszService, int nFamily = AF_INET);
  97. /**
  98. * Create from number. Initialize object from host or network format values (IPv4 only).
  99. * @param lIPAddr IP Address
  100. * @param nPort Port number
  101. * @param nFamily Socket address family (default: AF_INET)
  102. * @param bFmtHost flag to indicate that IP address and port are in host (true) or network format (false)
  103. * @return true if object is now valid
  104. */
  105. bool CreateFrom(ULONG lIPAddr, USHORT nPort, int nFamily = AF_INET, bool bFmtHost = true);
  106. /**
  107. * Object copy operator
  108. * @param sin reference object to copy from
  109. * @return reference of 'this' object
  110. */
  111. SockAddrIn& operator=(const SockAddrIn& sin) { return Copy( sin ); }
  112. /**
  113. * Equality operator
  114. * @param sin reference object to test
  115. * @return true if object is equal
  116. */
  117. bool operator==(const SockAddrIn& sin) const { return IsEqual( sin ); }
  118. /**
  119. * Not Equal operator
  120. * @param sin reference object to test
  121. * @return true if object is different
  122. */
  123. bool operator!=(const SockAddrIn& sin) const { return !IsEqual( sin ); }
  124. /**
  125. * SOCKADDR conversion. Return SOCKADDR of this object.
  126. */
  127. operator LPSOCKADDR() { return reinterpret_cast<LPSOCKADDR>(this); }
  128. /**
  129. * PIN6_ADDR conversion. Return const PIN6_ADDR of this object.
  130. */
  131. operator const IN6_ADDR*() const { return reinterpret_cast<const IN6_ADDR*>(this); }
  132. /**
  133. * PIN6_ADDR conversion. Return PIN6_ADDR of this object.
  134. */
  135. operator PIN6_ADDR() { return reinterpret_cast<PIN6_ADDR>(this); }
  136. /**
  137. * Size of this struct (SOCKADDR_IN) or (SOCKADDR_STORAGE) depending on address family
  138. * @return size of this structure (SOCKADDR_IN) or (SOCKADDR_STORAGE)
  139. */
  140. size_t Size() const { return (ss_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_storage); }
  141. /**
  142. * Initialize this object from SOCKADDR_IN struct.
  143. * @param psin SOCKADDR_IN object pointer
  144. */
  145. void SetAddr(const sockaddr_in* psin) { SetAddr(reinterpret_cast<const sockaddr_storage*>(psin)); }
  146. /**
  147. * Initialize this object from SOCKADDR_IN6 struct.
  148. * @param psin SOCKADDR_IN6 object pointer
  149. */
  150. void SetAddr(const sockaddr_in6* psin) { SetAddr(reinterpret_cast<const sockaddr_storage*>(psin)); }
  151. /**
  152. * Initialize this object from SOCKADDR_STORAGE struct.
  153. * @param pss SOCKADDR_STORAGE object pointer
  154. */
  155. void SetAddr(const sockaddr_storage* pss) { ss_family = pss->ss_family; memcpy(this, pss, Size()); }
  156. static SockAddrIn NULLAddr; ///< Null Address
  157. };
  158. #ifdef WIN32
  159. typedef LPWSAOVERLAPPED_COMPLETION_ROUTINE LPWSACOMPLETIONROUTINE;
  160. #endif
  161. #define SOCKET_SERVER_PORT 6432
  162. #define SOCKET_BUFFSIZE 1024 * 10 //注意, 这里单个包的大小不能超过该设置数值
  163. /**
  164. * CSocketHandle class
  165. * Socket communication class
  166. */
  167. class CSocketHandle
  168. {
  169. public:
  170. /**
  171. * Default constructor
  172. */
  173. CSocketHandle();
  174. /**
  175. * Destructor
  176. */
  177. ~CSocketHandle();
  178. /**
  179. * Check if socket is opened
  180. * @return true if this is opened (valid)
  181. */
  182. bool IsOpen() const;
  183. /**
  184. * Get SOCKET handle
  185. * @return SOCKET handle (handle is INVALID_SOCKET if object is closed)
  186. */
  187. SOCKET GetSocket() const;
  188. /**
  189. * Get SOCKET type
  190. * @return SOCKET type (-1 if not a valid socket)
  191. */
  192. int GetSocketType() const;
  193. /**
  194. * Attach a socket handle
  195. * This function may fail is socket handle is not valid or object already in used. Call Detach or Close to release object.
  196. * @param sock Socket handle to attach to this class
  197. * @return true if successful, otherwise false
  198. */
  199. bool Attach(SOCKET sock);
  200. /**
  201. * Detach a socket handle
  202. * @return previous socket handle or INVALID_SOCKET
  203. */
  204. SOCKET Detach();
  205. /**
  206. * Create a Socket - Server side.
  207. * @param pszHost hostname or IP address of adapter
  208. * @param pszServiceName Network service name or port number
  209. * @param nFamily address family to use (AF_INET, AF_INET6)
  210. * @param nType type of socket to create (SOCK_STREAM, SOCK_DGRAM)
  211. * @param uOptions Additional options (SO_BROADCAST, SO_REUSEADDR)
  212. * @return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error)
  213. * @sa InitLibrary, ConnectTo, IsOpen
  214. */
  215. bool CreateSocket(LPCTSTR pszHost, LPCTSTR pszServiceName, int nFamily, int nType, UINT uOptions = 0);
  216. /**
  217. * Create a socket, connect to a server - Client side.
  218. * @param pszHostName Hostname or NIC address
  219. * @param pszRemote Remote network address
  220. * @param pszServiceName Network service name or port number
  221. * @param nFamily address family to use (AF_INET, AF_INET6)
  222. * @param nType type of socket to create (SOCK_STREAM, SOCK_DGRAM)
  223. * @return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error)
  224. * @sa InitLibrary, CreateSocket, IsOpen
  225. */
  226. bool ConnectTo(LPCTSTR pszHostName, LPCTSTR pszRemote, LPCTSTR pszServiceName, int nFamily, int nType);
  227. /**
  228. * Close Socket
  229. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen
  230. */
  231. void Close();
  232. /**
  233. * Read from socket
  234. * @param lpBuffer Buffer to receive data
  235. * @param dwSize Size of buffer in bytes
  236. * @param lpAddrIn Peer address for UDP - this must be NULL for TCP
  237. * @param dwTimeout Read timeout in milliseconds
  238. * @return number of bytes read or (-1L) if fail
  239. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, Write, WriteEx
  240. */
  241. DWORD Read(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE);
  242. #ifdef WIN32
  243. /**
  244. * Read from socket (asynchronous mode).
  245. * @param lpBuffer Buffer to receive data
  246. * @param dwSize Size of buffer in bytes
  247. * @param lpAddrIn SockAddrIn for UDP - this must be NULL for TCP
  248. * @param lpOverlapped Windows Overlapped structure (required)
  249. * @param lpCompletionRoutine Winsock Completion routine (required)
  250. * @return number of bytes read, overlapped operation is pending or (-1L) if fail
  251. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, Write, WriteEx, IOControl, GetTransferOverlappedResult
  252. */
  253. DWORD ReadEx(LPBYTE lpBuffer, DWORD dwSize, LPSOCKADDR lpAddrIn,
  254. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine);
  255. #endif
  256. /**
  257. * Write to a destination socket
  258. * @param lpBuffer Buffer to send
  259. * @param dwCount Number of bytes to send
  260. * @param lpAddrIn Peer address for UDP - this must be NULL for TCP
  261. * @param dwTimeout Write timeout in milliseconds
  262. * @return number of bytes sent or (-1L) if fail
  263. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, ReadEx, WriteEx
  264. */
  265. DWORD Write(const LPBYTE lpBuffer, DWORD dwCount, const LPSOCKADDR lpAddrIn = NULL, DWORD dwTimeout = INFINITE);
  266. #ifdef WIN32
  267. /**
  268. * Write to a destination socket (asynchronous mode).
  269. * @param lpBuffer Buffer to send
  270. * @param dwCount Number of bytes to send
  271. * @param lpAddrIn SockAddrIn for UDP - this must be NULL for TCP
  272. * @param lpOverlapped Windows Overlapped structure (required)
  273. * @param lpCompletionRoutine Winsock Completion routine (required)
  274. * @return number of bytes read, overlapped operation is pending or (-1L) if fail
  275. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, Read, ReadEx, Write, IOControl, GetTransferOverlappedResult
  276. */
  277. DWORD WriteEx(const LPBYTE lpBuffer, DWORD dwCount, const LPSOCKADDR lpAddrIn,
  278. LPWSAOVERLAPPED lpOverlapped, LPWSACOMPLETIONROUTINE lpCompletionRoutine);
  279. #endif
  280. #ifdef WIN32
  281. /**
  282. * Control the mode of a socket (asynchronous mode)
  283. * @param dwIoCode Control code of operation to perform
  284. * @param lpInBuffer Pointer to the input buffer
  285. * @param cbInBuffer Size of the input buffer, in bytes
  286. * @param lpOutBuffer Pointer to the output buffer
  287. * @param cbOutBuffer Size of the output buffer, in bytes
  288. * @param lpcbBytesReturned Pointer to actual number of bytes of output
  289. * @param lpOverlapped Winsock Overlapped structure
  290. * @param lpCompletionRoutine Winsock Completion routine
  291. * @return true if successful, otherwise false (call WSAGetLastError() to retrieve latest error)
  292. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, WriteEx, GetTransferOverlappedResult
  293. */
  294. bool IOControl(DWORD dwIoCode, LPBYTE lpInBuffer, DWORD cbInBuffer,
  295. LPBYTE lpOutBuffer, DWORD cbOutBuffer,
  296. LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
  297. LPWSACOMPLETIONROUTINE lpCompletionRoutine);
  298. /**
  299. * Get Overlapped result (asynchronous mode)
  300. * @param lpOverlapped Windows Overlapped structure (required)
  301. * @param lpcbTransfer Pointer to get number of bytes transferred
  302. * @param bWait Force wait for overlapped operation to complete
  303. * @param lpdwFlags Optional flags (see MSDN on WSARecv API)
  304. * @sa InitLibrary, CreateSocket, ConnectTo, IsOpen, ReadEx, WriteEx, IOControl
  305. */
  306. bool GetTransferOverlappedResult(LPWSAOVERLAPPED lpOverlapped, LPDWORD lpcbTransfer, bool bWait = true, LPDWORD lpdwFlags = 0);
  307. #endif
  308. /**
  309. * Get Socket name - get local address
  310. * @param saddr_in current local address and port when connected
  311. * @return true if successful
  312. * @sa InitLibrary
  313. */
  314. bool GetSockName(SockAddrIn& saddr_in) const;
  315. /**
  316. * Get Peer Socket name - get peer address
  317. * @param saddr_in peer address and port (use only with TCP or client mode UDP)
  318. * @return true if successful
  319. * @sa InitLibrary
  320. */
  321. bool GetPeerName(SockAddrIn& saddr_in) const;
  322. /**
  323. * Register to multicast address
  324. * @param pszIPAddr multicast IP group
  325. * @param pszNIC interface IP address
  326. * @return true if successful
  327. * @sa InitLibrary
  328. */
  329. bool AddMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC);
  330. /**
  331. * Unregister from a multicast address
  332. * @param pszIPAddr multicast IP group
  333. * @param pszNIC interface IP address
  334. * @return true if successful
  335. * @sa InitLibrary
  336. */
  337. bool DropMembership(LPCTSTR pszIPAddr, LPCTSTR pszNIC);
  338. /**
  339. * Initialize Winsock library. This function calls WSAStartup.
  340. * @param wVersion Winsock version use MAKEWORD macro if possible (e.g.: MAKEWORD(2,2))
  341. * @return true if successful
  342. * @sa ReleaseLibrary
  343. */
  344. static bool InitLibrary(WORD wVersion);
  345. /**
  346. * Release Winsock library
  347. * @return true if successful
  348. * @sa InitLibrary
  349. */
  350. static bool ReleaseLibrary();
  351. /**
  352. * Wait for a new connection
  353. * @param sock A TCP socket handle. A new socket is return returned.
  354. * @return A new socket when a new client connects
  355. * @sa GetSocket, CreateSocket
  356. */
  357. static SOCKET WaitForConnection(SOCKET sock);
  358. /**
  359. * Shutdown a connection
  360. * @param sock Socket to shutdown communication
  361. * @return true if successful
  362. */
  363. static bool ShutdownConnection(SOCKET sock);
  364. /**
  365. * Check if IP address is unicast (network order).
  366. * @param ulAddr IP address (expected valid unicast address)
  367. * @return true if successful
  368. */
  369. static bool IsUnicastIP( ULONG ulAddr );
  370. /**
  371. * Check if IP address is multicast (network order).
  372. * @param ulAddr IP address (expected valid multicast address)
  373. * @return true if successful
  374. */
  375. static bool IsMulticastIP( ULONG ulAddr );
  376. /**
  377. * Format IP address to string
  378. * @param pszIPAddr Buffer to hold string
  379. * @param nSize Size of buffer in characters
  380. * @param ulAddr IP Address to format
  381. * @param bFmtHost Specify if address (ulAddr) is in host (true) or network format (false)
  382. * @return true if successful. Possible error could be INSUFFICIENT_BUFFER
  383. */
  384. static bool FormatIP(LPTSTR pszIPAddr, UINT nSize, ULONG ulAddr, bool bFmtHost);
  385. /**
  386. * Format IP address to string
  387. * @param pszIPAddr Buffer to hold string
  388. * @param nSize Size of buffer in characters
  389. * @param addrIn IP Address to format
  390. * @return true if successful. Possible error could be INSUFFICIENT_BUFFER
  391. */
  392. static bool FormatIP(LPTSTR pszIPAddr, UINT nSize, const SockAddrIn& addrIn);
  393. /**
  394. * Get service port number
  395. * @param pszServiceName Network service name (e.g.: "ftp", "telnet") or port number
  396. * @return port number
  397. */
  398. static USHORT GetPortNumber( LPCTSTR pszServiceName );
  399. /**
  400. * Get IP address of a host
  401. * @param pszHostName host name or IP address
  402. * @return Host IP address in host format
  403. * @sa GetAddressInfo
  404. */
  405. static ULONG GetIPAddress( LPCTSTR pszHostName );
  406. /**
  407. * Get current localname for this machine
  408. * @param pszName Buffer to receive host name
  409. * @param nSize Size of this buffer in character
  410. * @return true if successful
  411. */
  412. static bool GetLocalName(LPTSTR pszName, UINT nSize);
  413. /**
  414. * Get current (default) IP address for this machine
  415. * @param pszAddress Buffer to receive IP address (IPv4, IPv6 format)
  416. * @param nSize Size of this buffer in character
  417. * @param nFamily address family to use (AF_INET, AF_INET6)
  418. * @return true if successful
  419. */
  420. static bool GetLocalAddress(LPTSTR pszAddress, UINT nSize, int nFamily = AF_INET);
  421. /**
  422. * Get IP address info of a host (Supports: IPv4 and IPv6)
  423. * @param pszHostName host name or IP address
  424. * @param pszServiceName pszServiceName Network service name (e.g.: "ftp", "telnet") or port number
  425. * @param nFamily address family to use (AF_INET, AF_INET6)
  426. * @param sockAddr Socket address to fill in
  427. * @return true if successful
  428. */
  429. static bool GetAddressInfo( LPCTSTR pszHostName, LPCTSTR pszServiceName, int nFamily, SockAddrIn& sockAddr);
  430. // CSocketHandle - data
  431. protected:
  432. SOCKET m_hSocket; ///< socket handle
  433. public:
  434. char m_PendingBuffer[ SOCKET_BUFFSIZE ];
  435. int m_nPendingSize;
  436. CRITICAL_SECTION m_hClient2SrvSection;
  437. };
  438. /** @}*/
  439. #endif //SOCKETHANDLE_H