hsocket.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. BEGIN_EXTERN_C
  10. static inline int socket_errno() {
  11. #ifdef OS_WIN
  12. return WSAGetLastError();
  13. #else
  14. return errno;
  15. #endif
  16. }
  17. char* socket_strerror(int err);
  18. // socket -> setsockopt -> bind
  19. // @param type: SOCK_STREAM(tcp) SOCK_DGRAM(udp)
  20. // @return sockfd
  21. int Bind(int port, int type DEFAULT(SOCK_STREAM));
  22. // Bind -> listen
  23. // @return sockfd
  24. int Listen(int port);
  25. // @param host: domain or ip
  26. // @retval 0:succeed
  27. int Resolver(const char* host, struct sockaddr* addr);
  28. // @return sockfd
  29. // Resolver -> socket -> nonblocking -> connect
  30. int Connect(const char* host, int port, int nonblock DEFAULT(0));
  31. // Connect(host, port, 1)
  32. int ConnectNonblock(const char* host, int port);
  33. // Connect(host, port, 1) -> select -> blocking
  34. int ConnectTimeout(const char* host, int port, int ms);
  35. // @param cnt: ping count
  36. // @return: ok count
  37. // @note: printd $CC -DPRINT_DEBUG
  38. int Ping(const char* host, int cnt DEFAULT(4));
  39. #ifdef OS_WIN
  40. typedef int socklen_t;
  41. static inline int blocking(int sockfd) {
  42. unsigned long nb = 0;
  43. return ioctlsocket(sockfd, FIONBIO, &nb);
  44. }
  45. static inline int nonblocking(int sockfd) {
  46. unsigned long nb = 1;
  47. return ioctlsocket(sockfd, FIONBIO, &nb);
  48. }
  49. #define poll WSAPoll
  50. #undef EAGAIN
  51. #define EAGAIN WSAEWOULDBLOCK
  52. #undef EINPROGRESS
  53. #define EINPROGRESS WSAEINPROGRESS
  54. #undef ENOTSOCK
  55. #define ENOTSOCK WSAENOTSOCK
  56. #else
  57. #define blocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK)
  58. #define nonblocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK)
  59. typedef int SOCKET;
  60. #define INVALID_SOCKET -1
  61. #define closesocket close
  62. #endif
  63. static inline const char* sockaddr_ntop(const struct sockaddr* addr, char *ip, int len) {
  64. if (addr->sa_family == AF_INET) {
  65. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  66. return inet_ntop(AF_INET, &sin->sin_addr, ip, len);
  67. }
  68. else if (addr->sa_family == AF_INET6) {
  69. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  70. return inet_ntop(AF_INET6, &sin6->sin6_addr, ip, len);
  71. }
  72. return ip;
  73. }
  74. static inline uint16_t sockaddr_htons(const struct sockaddr* addr) {
  75. if (addr->sa_family == AF_INET) {
  76. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  77. return htons(sin->sin_port);
  78. }
  79. else if (addr->sa_family == AF_INET6) {
  80. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  81. return htons(sin6->sin6_port);
  82. }
  83. return 0;
  84. }
  85. static inline void sockaddr_printf(const struct sockaddr* addr) {
  86. char ip[INET6_ADDRSTRLEN] = {0};
  87. int port = 0;
  88. if (addr->sa_family == AF_INET) {
  89. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  90. inet_ntop(AF_INET, &sin->sin_addr, ip, sizeof(ip));
  91. port = htons(sin->sin_port);
  92. }
  93. else if (addr->sa_family == AF_INET6) {
  94. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  95. inet_ntop(AF_INET6, &sin6->sin6_addr, ip, sizeof(ip));
  96. port = htons(sin6->sin6_port);
  97. }
  98. printf("%s:%d\n", ip, port);
  99. }
  100. static inline const char* sockaddr_snprintf(const struct sockaddr* addr, char* buf, int len) {
  101. int port = 0;
  102. if (addr->sa_family == AF_INET) {
  103. struct sockaddr_in* sin = (struct sockaddr_in*)addr;
  104. inet_ntop(AF_INET, &sin->sin_addr, buf, len);
  105. port = htons(sin->sin_port);
  106. }
  107. else if (addr->sa_family == AF_INET6) {
  108. struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
  109. inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len);
  110. port = htons(sin6->sin6_port);
  111. }
  112. char sport[16] = {0};
  113. snprintf(sport, sizeof(sport), ":%d", port);
  114. safe_strncat(buf, sport, len);
  115. return buf;
  116. }
  117. static 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. static 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. static 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. static 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. static 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. static 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 // HW_SOCKET_H_