hsocket.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #ifndef HV_SOCKET_H_
  2. #define HV_SOCKET_H_
  3. /*
  4. * @功能:此头文件封装了跨平台的套接字操作
  5. *
  6. */
  7. #include "hexport.h"
  8. #include "hplatform.h"
  9. #ifdef ENABLE_UDS
  10. #include <sys/un.h> // import struct sockaddr_un
  11. #endif
  12. #ifdef _MSC_VER
  13. #pragma comment(lib, "ws2_32.lib")
  14. #endif
  15. #define LOCALHOST "127.0.0.1"
  16. #define ANYADDR "0.0.0.0"
  17. BEGIN_EXTERN_C
  18. HV_INLINE int socket_errno() {
  19. #ifdef OS_WIN
  20. return WSAGetLastError();
  21. #else
  22. return errno;
  23. #endif
  24. }
  25. HV_EXPORT const char* socket_strerror(int err);
  26. // 屏蔽一些windows和unix下套接字的差异
  27. #ifdef OS_WIN
  28. typedef int socklen_t;
  29. HV_INLINE int blocking(int sockfd) {
  30. unsigned long nb = 0;
  31. return ioctlsocket(sockfd, FIONBIO, &nb);
  32. }
  33. HV_INLINE int nonblocking(int sockfd) {
  34. unsigned long nb = 1;
  35. return ioctlsocket(sockfd, FIONBIO, &nb);
  36. }
  37. #define poll WSAPoll
  38. #undef EAGAIN
  39. #define EAGAIN WSAEWOULDBLOCK
  40. #undef EINPROGRESS
  41. #define EINPROGRESS WSAEINPROGRESS
  42. #undef ENOTSOCK
  43. #define ENOTSOCK WSAENOTSOCK
  44. #else
  45. #define blocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK)
  46. #define nonblocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK)
  47. typedef int SOCKET;
  48. #define INVALID_SOCKET -1
  49. #define closesocket close
  50. #endif
  51. //-----------------------------sockaddr_u----------------------------------------------
  52. // 定义了一个包含了IPv4、IPv6、Unix Domain Socket的联合类型
  53. typedef union {
  54. struct sockaddr sa;
  55. struct sockaddr_in sin;
  56. struct sockaddr_in6 sin6;
  57. #ifdef ENABLE_UDS
  58. struct sockaddr_un sun;
  59. #endif
  60. } sockaddr_u;
  61. // 域名解析
  62. // @param host: domain or ip
  63. // @retval 0:succeed
  64. HV_EXPORT int Resolver(const char* host, sockaddr_u* addr);
  65. // 提供了一系列操作sockaddr_u的工具函数
  66. HV_EXPORT const char* sockaddr_ip(sockaddr_u* addr, char *ip, int len);
  67. HV_EXPORT uint16_t sockaddr_port(sockaddr_u* addr);
  68. HV_EXPORT int sockaddr_set_ip(sockaddr_u* addr, const char* host);
  69. HV_EXPORT void sockaddr_set_port(sockaddr_u* addr, int port);
  70. HV_EXPORT int sockaddr_set_ipport(sockaddr_u* addr, const char* host, int port);
  71. HV_EXPORT socklen_t sockaddr_len(sockaddr_u* addr);
  72. HV_EXPORT const char* sockaddr_str(sockaddr_u* addr, char* buf, int len);
  73. //#define INET_ADDRSTRLEN 16
  74. //#define INET6_ADDRSTRLEN 46
  75. #ifdef ENABLE_UDS
  76. #define SOCKADDR_STRLEN sizeof(((struct sockaddr_un*)(NULL))->sun_path)
  77. HV_INLINE void sockaddr_set_path(sockaddr_u* addr, const char* path) {
  78. addr->sa.sa_family = AF_UNIX;
  79. strncpy(addr->sun.sun_path, path, sizeof(addr->sun.sun_path));
  80. }
  81. #else
  82. #define SOCKADDR_STRLEN 64 // ipv4:port | [ipv6]:port
  83. #endif
  84. HV_INLINE void sockaddr_print(sockaddr_u* addr) {
  85. char buf[SOCKADDR_STRLEN] = {0};
  86. sockaddr_str(addr, buf, sizeof(buf));
  87. puts(buf);
  88. }
  89. #define SOCKADDR_LEN(addr) sockaddr_len((sockaddr_u*)addr)
  90. #define SOCKADDR_STR(addr, buf) sockaddr_str((sockaddr_u*)addr, buf, sizeof(buf))
  91. #define SOCKADDR_PRINT(addr) sockaddr_print((sockaddr_u*)addr)
  92. //=====================================================================================
  93. // socket -> setsockopt -> bind
  94. // @param type: SOCK_STREAM(tcp) SOCK_DGRAM(udp)
  95. // @return sockfd
  96. HV_EXPORT int Bind(int port, const char* host DEFAULT(ANYADDR), int type DEFAULT(SOCK_STREAM));
  97. // Bind -> listen
  98. // @return listenfd
  99. HV_EXPORT int Listen(int port, const char* host DEFAULT(ANYADDR));
  100. // @return connfd
  101. // Resolver -> socket -> nonblocking -> connect
  102. HV_EXPORT int Connect(const char* host, int port, int nonblock DEFAULT(0));
  103. // Connect(host, port, 1)
  104. HV_EXPORT int ConnectNonblock(const char* host, int port);
  105. // Connect(host, port, 1) -> select -> blocking
  106. #define DEFAULT_CONNECT_TIMEOUT 5000 // ms
  107. HV_EXPORT int ConnectTimeout(const char* host, int port, int ms DEFAULT(DEFAULT_CONNECT_TIMEOUT));
  108. #ifdef ENABLE_UDS
  109. HV_EXPORT int BindUnix(const char* path, int type DEFAULT(SOCK_STREAM));
  110. HV_EXPORT int ListenUnix(const char* path);
  111. HV_EXPORT int ConnectUnix(const char* path, int nonblock DEFAULT(0));
  112. HV_EXPORT int ConnectUnixNonblock(const char* path);
  113. HV_EXPORT int ConnectUnixTimeout(const char* path, int ms DEFAULT(DEFAULT_CONNECT_TIMEOUT));
  114. #endif
  115. // Just implement Socketpair(AF_INET, SOCK_STREAM, 0, sv);
  116. HV_EXPORT int Socketpair(int family, int type, int protocol, int sv[2]);
  117. HV_INLINE int tcp_nodelay(int sockfd, int on DEFAULT(1)) {
  118. return setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(int));
  119. }
  120. HV_INLINE int tcp_nopush(int sockfd, int on DEFAULT(1)) {
  121. #ifdef TCP_NOPUSH
  122. return setsockopt(sockfd, IPPROTO_TCP, TCP_NOPUSH, (const char*)&on, sizeof(int));
  123. #elif defined(TCP_CORK)
  124. return setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, (const char*)&on, sizeof(int));
  125. #else
  126. return -10;
  127. #endif
  128. }
  129. HV_INLINE int tcp_keepalive(int sockfd, int on DEFAULT(1), int delay DEFAULT(60)) {
  130. if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(int)) != 0) {
  131. return socket_errno();
  132. }
  133. #ifdef TCP_KEEPALIVE
  134. return setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, (const char*)&delay, sizeof(int));
  135. #elif defined(TCP_KEEPIDLE)
  136. // TCP_KEEPIDLE => tcp_keepalive_time
  137. // TCP_KEEPCNT => tcp_keepalive_probes
  138. // TCP_KEEPINTVL => tcp_keepalive_intvl
  139. return setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (const char*)&delay, sizeof(int));
  140. #else
  141. return 0;
  142. #endif
  143. }
  144. HV_INLINE int udp_broadcast(int sockfd, int on DEFAULT(1)) {
  145. return setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof(int));
  146. }
  147. // send timeout
  148. HV_INLINE int so_sndtimeo(int sockfd, int timeout) {
  149. #ifdef OS_WIN
  150. return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(int));
  151. #else
  152. struct timeval tv = {timeout/1000, (timeout%1000)*1000};
  153. return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
  154. #endif
  155. }
  156. // recv timeout
  157. HV_INLINE int so_rcvtimeo(int sockfd, int timeout) {
  158. #ifdef OS_WIN
  159. return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(int));
  160. #else
  161. struct timeval tv = {timeout/1000, (timeout%1000)*1000};
  162. return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  163. #endif
  164. }
  165. END_EXTERN_C
  166. #endif // HV_SOCKET_H_