hsocket.h 5.6 KB

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