1
0

hsocket.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #ifndef HW_SOCKET_H_
  2. #define HW_SOCKET_H_
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #include "hbase.h"
  6. #ifdef _MSC_VER
  7. #pragma comment(lib, "ws2_32.lib")
  8. #endif
  9. #define LOCALHOST "127.0.0.1"
  10. #define ANYADDR "0.0.0.0"
  11. BEGIN_EXTERN_C
  12. static inline int socket_errno() {
  13. #ifdef OS_WIN
  14. return WSAGetLastError();
  15. #else
  16. return errno;
  17. #endif
  18. }
  19. char* socket_strerror(int err);
  20. // @param host: domain or ip
  21. // @retval 0:succeed
  22. int Resolver(const char* host, struct sockaddr* addr);
  23. // socket -> setsockopt -> bind
  24. // @param type: SOCK_STREAM(tcp) SOCK_DGRAM(udp)
  25. // @return sockfd
  26. int Bind(int port, const char* host DEFAULT(ANYADDR), int type DEFAULT(SOCK_STREAM));
  27. // Bind -> listen
  28. // @return sockfd
  29. int Listen(int port, const char* host DEFAULT(ANYADDR));
  30. // @return sockfd
  31. // Resolver -> socket -> nonblocking -> connect
  32. int Connect(const char* host, int port, int nonblock DEFAULT(0));
  33. // Connect(host, port, 1)
  34. int ConnectNonblock(const char* host, int port);
  35. // Connect(host, port, 1) -> select -> blocking
  36. #define DEFAULT_CONNECT_TIMEOUT 5000 // ms
  37. int ConnectTimeout(const char* host, int port, int ms DEFAULT(DEFAULT_CONNECT_TIMEOUT));
  38. // @param cnt: ping count
  39. // @return: ok count
  40. // @note: printd $CC -DPRINT_DEBUG
  41. int Ping(const char* host, int cnt DEFAULT(4));
  42. #ifdef OS_WIN
  43. typedef int socklen_t;
  44. static inline int blocking(int sockfd) {
  45. unsigned long nb = 0;
  46. return ioctlsocket(sockfd, FIONBIO, &nb);
  47. }
  48. static inline int nonblocking(int sockfd) {
  49. unsigned long nb = 1;
  50. return ioctlsocket(sockfd, FIONBIO, &nb);
  51. }
  52. #define poll WSAPoll
  53. #undef EAGAIN
  54. #define EAGAIN WSAEWOULDBLOCK
  55. #undef EINPROGRESS
  56. #define EINPROGRESS WSAEINPROGRESS
  57. #undef ENOTSOCK
  58. #define ENOTSOCK WSAENOTSOCK
  59. #else
  60. #define blocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK)
  61. #define nonblocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK)
  62. typedef int SOCKET;
  63. #define INVALID_SOCKET -1
  64. #define closesocket close
  65. #endif
  66. static inline const char* sockaddr_ntop(const struct sockaddr* addr, char *ip, int len) {
  67. if (addr->sa_family == AF_INET) {
  68. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  69. return inet_ntop(AF_INET, &sin->sin_addr, ip, len);
  70. }
  71. else if (addr->sa_family == AF_INET6) {
  72. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  73. return inet_ntop(AF_INET6, &sin6->sin6_addr, ip, len);
  74. }
  75. return ip;
  76. }
  77. static inline uint16_t sockaddr_htons(const struct sockaddr* addr) {
  78. if (addr->sa_family == AF_INET) {
  79. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  80. return htons(sin->sin_port);
  81. }
  82. else if (addr->sa_family == AF_INET6) {
  83. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  84. return htons(sin6->sin6_port);
  85. }
  86. return 0;
  87. }
  88. static inline void sockaddr_printf(const struct sockaddr* addr) {
  89. char ip[INET6_ADDRSTRLEN] = {0};
  90. int port = 0;
  91. if (addr->sa_family == AF_INET) {
  92. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  93. inet_ntop(AF_INET, &sin->sin_addr, ip, sizeof(ip));
  94. port = htons(sin->sin_port);
  95. }
  96. else if (addr->sa_family == AF_INET6) {
  97. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  98. inet_ntop(AF_INET6, &sin6->sin6_addr, ip, sizeof(ip));
  99. port = htons(sin6->sin6_port);
  100. }
  101. printf("%s:%d\n", ip, port);
  102. }
  103. static inline const char* sockaddr_snprintf(const struct sockaddr* addr, char* buf, int len) {
  104. int port = 0;
  105. if (addr->sa_family == AF_INET) {
  106. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  107. inet_ntop(AF_INET, &sin->sin_addr, buf, len);
  108. port = htons(sin->sin_port);
  109. }
  110. else if (addr->sa_family == AF_INET6) {
  111. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  112. inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len);
  113. port = htons(sin6->sin6_port);
  114. }
  115. char sport[16] = {0};
  116. snprintf(sport, sizeof(sport), ":%d", port);
  117. safe_strncat(buf, sport, len);
  118. return buf;
  119. }
  120. static inline int tcp_nodelay(int sockfd, int on DEFAULT(1)) {
  121. return setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(int));
  122. }
  123. static inline int tcp_nopush(int sockfd, int on DEFAULT(1)) {
  124. #ifdef TCP_NOPUSH
  125. return setsockopt(sockfd, IPPROTO_TCP, TCP_NOPUSH, (const char*)&on, sizeof(int));
  126. #elif defined(TCP_CORK)
  127. return setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, (const char*)&on, sizeof(int));
  128. #else
  129. return -10;
  130. #endif
  131. }
  132. static inline int tcp_keepalive(int sockfd, int on DEFAULT(1), int delay DEFAULT(60)) {
  133. if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(int)) != 0) {
  134. return socket_errno();
  135. }
  136. #ifdef TCP_KEEPALIVE
  137. return setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, (const char*)&delay, sizeof(int));
  138. #elif defined(TCP_KEEPIDLE)
  139. // TCP_KEEPIDLE => tcp_keepalive_time
  140. // TCP_KEEPCNT => tcp_keepalive_probes
  141. // TCP_KEEPINTVL => tcp_keepalive_intvl
  142. return setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (const char*)&delay, sizeof(int));
  143. #else
  144. return 0;
  145. #endif
  146. }
  147. static inline int udp_broadcast(int sockfd, int on DEFAULT(1)) {
  148. return setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof(int));
  149. }
  150. // send timeout
  151. static inline int so_sndtimeo(int sockfd, int timeout) {
  152. #ifdef OS_WIN
  153. return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(int));
  154. #else
  155. struct timeval tv = {timeout/1000, (timeout%1000)*1000};
  156. return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
  157. #endif
  158. }
  159. // recv timeout
  160. static inline int so_rcvtimeo(int sockfd, int timeout) {
  161. #ifdef OS_WIN
  162. return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(int));
  163. #else
  164. struct timeval tv = {timeout/1000, (timeout%1000)*1000};
  165. return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  166. #endif
  167. }
  168. END_EXTERN_C
  169. #endif // HW_SOCKET_H_