sockutil.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLToolKit(https://github.com/xia-chu/ZLToolKit).
  5. *
  6. * Use of this source code is governed by MIT license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef NETWORK_SOCKUTIL_H
  11. #define NETWORK_SOCKUTIL_H
  12. #if defined(_WIN32)
  13. #include <winsock2.h>
  14. #include <ws2tcpip.h>
  15. #include <Iphlpapi.h>
  16. #pragma comment (lib, "Ws2_32.lib")
  17. #pragma comment(lib,"Iphlpapi.lib")
  18. #else
  19. #include <netdb.h>
  20. #include <arpa/inet.h>
  21. #include <sys/ioctl.h>
  22. #include <sys/socket.h>
  23. #include <net/if.h>
  24. #include <netinet/in.h>
  25. #include <netinet/tcp.h>
  26. #endif // defined(_WIN32)
  27. #include <map>
  28. #include <vector>
  29. #include <string>
  30. #include <string.h>
  31. #include <stdint.h>
  32. using namespace std;
  33. namespace toolkit {
  34. #if defined(_WIN32)
  35. #ifndef socklen_t
  36. #define socklen_t int
  37. #endif //!socklen_t
  38. #ifndef SHUT_RDWR
  39. #define SHUT_RDWR 2
  40. #endif //!SHUT_RDWR
  41. int ioctl(int fd, long cmd, u_long *ptr);
  42. int close(int fd);
  43. #endif // defined(_WIN32)
  44. #define SOCKET_DEFAULT_BUF_SIZE (256 * 1024)
  45. //套接字工具类,封装了socket、网络的一些基本操作
  46. class SockUtil {
  47. public:
  48. /**
  49. * 创建tcp客户端套接字并连接服务器
  50. * @param host 服务器ip或域名
  51. * @param port 服务器端口号
  52. * @param bAsync 是否异步连接
  53. * @param localIp 绑定的本地网卡ip
  54. * @param localPort 绑定的本地端口号
  55. * @return -1代表失败,其他为socket fd号
  56. */
  57. static int connect(const char *host, uint16_t port, bool bAsync = true,const char *localIp = "0.0.0.0",uint16_t localPort = 0);
  58. /**
  59. * 创建tcp监听套接字
  60. * @param port 监听的本地端口
  61. * @param localIp 绑定的本地网卡ip
  62. * @param backLog accept列队长度
  63. * @return -1代表失败,其他为socket fd号
  64. */
  65. static int listen(const uint16_t port, const char *localIp = "0.0.0.0", int backLog = 1024);
  66. /**
  67. * 创建udp套接字
  68. * @param port 监听的本地端口
  69. * @param localIp 绑定的本地网卡ip
  70. * @return -1代表失败,其他为socket fd号
  71. */
  72. static int bindUdpSock(const uint16_t port, const char *localIp = "0.0.0.0");
  73. /**
  74. * @brief 初始化套接字 sock 连接关系
  75. * @param sock, socket fd 号
  76. * @param addr, 对端地址
  77. * @param addr_len
  78. * @return 0 成功, -1 失败
  79. */
  80. static int connectUdpSock(int sock, struct sockaddr *addr, int addr_len);
  81. /**
  82. * @brief 解除与 sock 相关的绑定关系
  83. * @param sock, socket fd 号
  84. * @return 0 成功, -1 失败
  85. */
  86. static int dissolveUdpSock(int sock);
  87. /**
  88. * 绑定socket fd至某个网卡和端口
  89. * @param sock socket fd号
  90. * @param localIp 绑定的本地网卡ip
  91. * @param port 绑定的本地端口
  92. * @return 0代表成功,-1为失败
  93. */
  94. static int bindSock(int sock,const char *localIp,uint16_t port);
  95. /**
  96. * 开启TCP_NODELAY,降低TCP交互延时
  97. * @param sock socket fd号
  98. * @param on 是否开启
  99. * @return 0代表成功,-1为失败
  100. */
  101. static int setNoDelay(int sock, bool on = true);
  102. /**
  103. * 写socket不触发SIG_PIPE信号(貌似只有mac有效)
  104. * @param sock socket fd号
  105. * @return 0代表成功,-1为失败
  106. */
  107. static int setNoSigpipe(int sock);
  108. /**
  109. * 设置读写socket是否阻塞
  110. * @param sock socket fd号
  111. * @param noblock 是否阻塞
  112. * @return 0代表成功,-1为失败
  113. */
  114. static int setNoBlocked(int sock, bool noblock = true);
  115. /**
  116. * 设置socket接收缓存,默认貌似8K左右,一般有设置上限
  117. * 可以通过配置内核配置文件调整
  118. * @param sock socket fd号
  119. * @param size 接收缓存大小
  120. * @return 0代表成功,-1为失败
  121. */
  122. static int setRecvBuf(int sock, int size = SOCKET_DEFAULT_BUF_SIZE);
  123. /**
  124. * 设置socket接收缓存,默认貌似8K左右,一般有设置上限
  125. * 可以通过配置内核配置文件调整
  126. * @param sock socket fd号
  127. * @param size 接收缓存大小
  128. * @return 0代表成功,-1为失败
  129. */
  130. static int setSendBuf(int sock, int size = SOCKET_DEFAULT_BUF_SIZE);
  131. /**
  132. * 设置后续可绑定复用端口(处于TIME_WAITE状态)
  133. * @param sock socket fd号
  134. * @param on 是否开启该特性
  135. * @return 0代表成功,-1为失败
  136. */
  137. static int setReuseable(int sock, bool on = true, bool reuse_port = true);
  138. /**
  139. * 运行发送或接收udp广播信息
  140. * @param sock socket fd号
  141. * @param on 是否开启该特性
  142. * @return 0代表成功,-1为失败
  143. */
  144. static int setBroadcast(int sock, bool on = true);
  145. /**
  146. * 是否开启TCP KeepAlive特性
  147. * @param sock socket fd号
  148. * @param on 是否开启该特性
  149. * @return 0代表成功,-1为失败
  150. */
  151. static int setKeepAlive(int sock, bool on = true);
  152. /**
  153. * 是否开启FD_CLOEXEC特性(多进程相关)
  154. * @param fd fd号,不一定是socket
  155. * @param on 是否开启该特性
  156. * @return 0代表成功,-1为失败
  157. */
  158. static int setCloExec(int fd, bool on = true);
  159. /**
  160. * 开启SO_LINGER特性
  161. * @param sock socket fd号
  162. * @param second 内核等待关闭socket超时时间,单位秒
  163. * @return 0代表成功,-1为失败
  164. */
  165. static int setCloseWait(int sock, int second = 0);
  166. /**
  167. * dns解析
  168. * @param host 域名或ip
  169. * @param port 端口号
  170. * @param addr sockaddr结构体
  171. * @return 是否成功
  172. */
  173. static bool getDomainIP(const char *host,uint16_t port,struct sockaddr &addr);
  174. /**
  175. * 设置组播ttl
  176. * @param sock socket fd号
  177. * @param ttl ttl值
  178. * @return 0代表成功,-1为失败
  179. */
  180. static int setMultiTTL(int sock, uint8_t ttl = 64);
  181. /**
  182. * 设置组播发送网卡
  183. * @param sock socket fd号
  184. * @param strLocalIp 本机网卡ip
  185. * @return 0代表成功,-1为失败
  186. */
  187. static int setMultiIF(int sock, const char *strLocalIp);
  188. /**
  189. * 设置是否接收本机发出的组播包
  190. * @param sock socket fd号
  191. * @param bAccept 是否接收
  192. * @return 0代表成功,-1为失败
  193. */
  194. static int setMultiLOOP(int sock, bool bAccept = false);
  195. /**
  196. * 加入组播
  197. * @param sock socket fd号
  198. * @param strAddr 组播地址
  199. * @param strLocalIp 本机网卡ip
  200. * @return 0代表成功,-1为失败
  201. */
  202. static int joinMultiAddr(int sock, const char *strAddr, const char* strLocalIp = "0.0.0.0");
  203. /**
  204. * 退出组播
  205. * @param sock socket fd号
  206. * @param strAddr 组播地址
  207. * @param strLocalIp 本机网卡ip
  208. * @return 0代表成功,-1为失败
  209. */
  210. static int leaveMultiAddr(int sock, const char *strAddr, const char* strLocalIp = "0.0.0.0");
  211. /**
  212. * 加入组播并只接受该源端的组播数据
  213. * @param sock socket fd号
  214. * @param strAddr 组播地址
  215. * @param strSrcIp 数据源端地址
  216. * @param strLocalIp 本机网卡ip
  217. * @return 0代表成功,-1为失败
  218. */
  219. static int joinMultiAddrFilter(int sock, const char* strAddr, const char* strSrcIp, const char* strLocalIp = "0.0.0.0");
  220. /**
  221. * 退出组播
  222. * @param sock socket fd号
  223. * @param strAddr 组播地址
  224. * @param strSrcIp 数据源端地址
  225. * @param strLocalIp 本机网卡ip
  226. * @return 0代表成功,-1为失败
  227. */
  228. static int leaveMultiAddrFilter(int sock, const char* strAddr, const char* strSrcIp, const char* strLocalIp = "0.0.0.0");
  229. /**
  230. * 获取该socket当前发生的错误
  231. * @param sock socket fd号
  232. * @return 错误代码
  233. */
  234. static int getSockError(int sock);
  235. /**
  236. * 获取网卡列表
  237. * @return vector<map<ip:name> >
  238. */
  239. static vector<map<string,string> > getInterfaceList();
  240. /**
  241. * 获取本机默认网卡ip
  242. */
  243. static string get_local_ip();
  244. /**
  245. * 获取该socket绑定的本地ip
  246. * @param sock socket fd号
  247. */
  248. static string get_local_ip(int sock);
  249. /**
  250. * 获取该socket绑定的本地端口
  251. * @param sock socket fd号
  252. */
  253. static uint16_t get_local_port(int sock);
  254. /**
  255. * 获取该socket绑定的远端ip
  256. * @param sock socket fd号
  257. */
  258. static string get_peer_ip(int sock);
  259. /**
  260. * 获取该socket绑定的远端端口
  261. * @param sock socket fd号
  262. */
  263. static uint16_t get_peer_port(int sock);
  264. /**
  265. * 线程安全的in_addr转ip字符串
  266. */
  267. static string inet_ntoa(struct in_addr &addr);
  268. /**
  269. * 获取网卡ip
  270. * @param ifrName 网卡名
  271. */
  272. static string get_ifr_ip(const char *ifrName);
  273. /**
  274. * 获取网卡名
  275. * @param localIp 网卡ip
  276. */
  277. static string get_ifr_name(const char *localIp);
  278. /**
  279. * 根据网卡名获取子网掩码
  280. * @param ifrName 网卡名
  281. */
  282. static string get_ifr_mask(const char *ifrName);
  283. /**
  284. * 根据网卡名获取广播地址
  285. * @param ifrName 网卡名
  286. */
  287. static string get_ifr_brdaddr(const char *ifrName);
  288. /**
  289. * 判断两个ip是否为同一网段
  290. * @param myIp 我的ip
  291. * @param dstIp 对方ip
  292. */
  293. static bool in_same_lan(const char *myIp, const char *dstIp);
  294. };
  295. } // namespace toolkit
  296. #endif // !NETWORK_SOCKUTIL_H