tc_socket.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "util/tc_platform.h"
  17. #if TARGET_PLATFORM_LINUX||TARGET_PLATFORM_IOS
  18. #include <unistd.h>
  19. #include <fcntl.h>
  20. #include <netdb.h>
  21. #include <arpa/inet.h>
  22. #ifndef TARGET_PLATFORM_ANDROID
  23. #include <ifaddrs.h>
  24. #endif
  25. #include <sys/ioctl.h>
  26. #include <net/if.h>
  27. #ifndef TARGET_PLATFORM_IOS
  28. #include <net/if_arp.h>
  29. #endif
  30. #include <netinet/tcp.h>
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <string.h>
  34. #else
  35. #include <WS2tcpip.h>
  36. #define bzero(b,len) (memset((b), '\0', (len)))
  37. #endif
  38. #include <cerrno>
  39. #include <cassert>
  40. #include "util/tc_port.h"
  41. #include "util/tc_socket.h"
  42. namespace tars
  43. {
  44. TC_Socket::TC_Socket() : _sock(INVALID_SOCKET), _bOwner(true), _iDomain(AF_INET)
  45. {
  46. }
  47. TC_Socket::~TC_Socket()
  48. {
  49. if(_bOwner)
  50. {
  51. close();
  52. }
  53. }
  54. void TC_Socket::init(int fd, bool bOwner, int iDomain)
  55. {
  56. if(_bOwner)
  57. {
  58. close();
  59. }
  60. _sock = fd;
  61. _bOwner = bOwner;
  62. _iDomain = iDomain;
  63. }
  64. void TC_Socket::createSocket(int iSocketType, int iDomain)
  65. {
  66. // assert(iSocketType == SOCK_STREAM || iSocketType == SOCK_DGRAM);
  67. close();
  68. _iDomain = iDomain;
  69. _sock = socket(iDomain, iSocketType, 0);
  70. if(_sock < 0)
  71. {
  72. _sock = INVALID_SOCKET;
  73. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::createSocket] create socket error");
  74. // throw TC_Socket_Exception("[TC_Socket::createSocket] create socket error! :" + string(strerror(errno)));
  75. }
  76. else
  77. {
  78. ignoreSigPipe();
  79. }
  80. }
  81. void TC_Socket::getPeerName(string &sPeerAddress, uint16_t &iPeerPort) const
  82. {
  83. assert(_iDomain == AF_INET || _iDomain == AF_INET6);
  84. char sAddr[INET6_ADDRSTRLEN] = "\0";
  85. struct sockaddr_in stPeer4;
  86. struct sockaddr_in6 stPeer6;
  87. struct sockaddr *stPeer = (AF_INET6 == _iDomain) ? (struct sockaddr *)&stPeer6 : (struct sockaddr *)&stPeer4;
  88. socklen_t iPeerLen = (AF_INET6 == _iDomain) ? sizeof(stPeer6) : sizeof(stPeer4);
  89. bzero(stPeer, iPeerLen);
  90. getPeerName(stPeer, iPeerLen);
  91. inet_ntop(_iDomain, (AF_INET6 == _iDomain) ? (void*)&stPeer6.sin6_addr : (void *)&stPeer4.sin_addr, sAddr, sizeof(sAddr));
  92. sPeerAddress = sAddr;
  93. iPeerPort = (AF_INET6 == _iDomain) ? ntohs(stPeer6.sin6_port) : ntohs(stPeer4.sin_port);
  94. }
  95. #if TARGET_PLATFORM_LINUX||TARGET_PLATFORM_IOS
  96. void TC_Socket::getPeerName(string &sPathName) const
  97. {
  98. assert(_iDomain == AF_LOCAL);
  99. struct sockaddr_un stSock;
  100. bzero(&stSock, sizeof(struct sockaddr_un));
  101. SOCKET_LEN_TYPE iSockLen = sizeof(stSock);
  102. getPeerName((struct sockaddr *)&stSock, iSockLen);
  103. sPathName = stSock.sun_path;
  104. }
  105. void TC_Socket::getSockName(string &sPathName) const
  106. {
  107. assert(_iDomain == AF_LOCAL);
  108. struct sockaddr_un stSock;
  109. bzero(&stSock, sizeof(struct sockaddr_un));
  110. SOCKET_LEN_TYPE iSockLen = sizeof(stSock);
  111. getSockName((struct sockaddr *)&stSock, iSockLen);
  112. sPathName = stSock.sun_path;
  113. }
  114. void TC_Socket::bind(const char *sPathName)
  115. {
  116. assert(_iDomain == AF_LOCAL);
  117. unlink(sPathName);
  118. struct sockaddr_un stBindAddr;
  119. memset(&stBindAddr, 0x00, sizeof(stBindAddr));
  120. stBindAddr.sun_family = _iDomain;
  121. strncpy(stBindAddr.sun_path, sPathName, sizeof(stBindAddr.sun_path));
  122. try
  123. {
  124. bind((struct sockaddr *)&stBindAddr, sizeof(stBindAddr));
  125. }
  126. catch(const std::exception& e)
  127. {
  128. std::cerr << e.what() << ", " << sPathName << endl;
  129. throw e;
  130. }
  131. }
  132. void TC_Socket::connect(const char *sPathName)
  133. {
  134. int ret = connectNoThrow(sPathName);
  135. if(ret < 0)
  136. {
  137. THROW_EXCEPTION_SYSCODE(TC_SocketConnect_Exception, "[TC_Socket::connect] connect error");
  138. }
  139. }
  140. int TC_Socket::connectNoThrow(const char *sPathName)
  141. {
  142. assert(_iDomain == AF_LOCAL);
  143. struct sockaddr_un stServerAddr;
  144. memset(&stServerAddr, 0x00, sizeof(stServerAddr));
  145. stServerAddr.sun_family = _iDomain;
  146. strncpy(stServerAddr.sun_path, sPathName, sizeof(stServerAddr.sun_path));
  147. return connect((struct sockaddr *)&stServerAddr, sizeof(stServerAddr));
  148. }
  149. #endif
  150. void TC_Socket::getPeerName(struct sockaddr *pstPeerAddr, SOCKET_LEN_TYPE &iPeerLen) const
  151. {
  152. if(getpeername(_sock, pstPeerAddr, &iPeerLen) < 0)
  153. {
  154. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getPeerName] getpeername error");
  155. }
  156. }
  157. void TC_Socket::getSockName(string &sSockAddress, uint16_t &iSockPort) const
  158. {
  159. assert(_iDomain == AF_INET || _iDomain == AF_INET6);
  160. char sAddr[INET6_ADDRSTRLEN] = "\0";
  161. struct sockaddr_in6 in6;
  162. struct sockaddr_in in4;
  163. struct sockaddr *in = (AF_INET6 == _iDomain) ? (struct sockaddr *)&in6 : (struct sockaddr *)&in4;
  164. socklen_t len = (AF_INET6 == _iDomain) ? sizeof(in6) : sizeof(in4);
  165. bzero(in, len);
  166. getSockName(in, len);
  167. inet_ntop(_iDomain, (AF_INET6 == _iDomain) ? (void *)&in6.sin6_addr : (void *)&in4.sin_addr, sAddr, sizeof(sAddr));
  168. sSockAddress = sAddr;
  169. iSockPort = (AF_INET6 == _iDomain) ? ntohs(in6.sin6_port) : ntohs(in4.sin_port);
  170. }
  171. void TC_Socket::getSockName(struct sockaddr *pstSockAddr, SOCKET_LEN_TYPE &iSockLen) const
  172. {
  173. if(getsockname(_sock, pstSockAddr, &iSockLen) < 0)
  174. {
  175. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getSockName] getsockname error");
  176. }
  177. }
  178. SOCKET_TYPE TC_Socket::accept(TC_Socket &tcSock, struct sockaddr *pstSockAddr, SOCKET_LEN_TYPE &iSockLen)
  179. {
  180. assert(tcSock._sock == INVALID_SOCKET);
  181. SOCKET_TYPE ifd;
  182. #if TARGET_PLATFORM_WINDOWS
  183. ifd = ::accept(_sock, pstSockAddr, &iSockLen);
  184. #else
  185. while ((ifd = ::accept(_sock, pstSockAddr, &iSockLen)) < 0 && errno == EINTR);
  186. #endif
  187. tcSock._sock = ifd;
  188. tcSock._iDomain = _iDomain;
  189. return tcSock._sock;
  190. }
  191. void TC_Socket::parseAddr(const string &sAddr, struct in_addr &stSinAddr)
  192. {
  193. int iRet = inet_pton(AF_INET, sAddr.c_str(), &stSinAddr);
  194. if(iRet < 0)
  195. {
  196. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] inet_pton(" + sAddr + ") error");
  197. }
  198. #if TARGET_PLATFORM_LINUX
  199. else if (iRet == 0)
  200. {
  201. struct hostent stHostent;
  202. struct hostent *pstHostent;
  203. char buf[2048] = "\0";
  204. int iError;
  205. gethostbyname_r(sAddr.c_str(), &stHostent, buf, sizeof(buf), &pstHostent, &iError);
  206. if (pstHostent == NULL)
  207. {
  208. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] gethostbyname_r(" + sAddr + ") error");
  209. // throw TC_Socket_Exception("[TC_Socket::parseAddr] gethostbyname_r(" + sAddr + ") error", TC_Exception::getSystemCode());
  210. }
  211. else
  212. {
  213. stSinAddr = *(struct in_addr *) pstHostent->h_addr;
  214. }
  215. }
  216. #else
  217. else if(iRet == 0)
  218. {
  219. struct addrinfo *ailist;
  220. struct addrinfo hints;
  221. memset(&hints, 0, sizeof(hints));
  222. hints.ai_family = PF_UNSPEC;
  223. hints.ai_socktype = SOCK_STREAM;
  224. int err = getaddrinfo(sAddr.c_str(), NULL, &hints, &ailist);
  225. if (err != 0)
  226. {
  227. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] getaddrinfo(" + sAddr + ") error");
  228. }
  229. else
  230. {
  231. for (addrinfo *aip = ailist; aip != NULL; aip = aip->ai_next) {
  232. if (aip->ai_family == AF_INET) {
  233. stSinAddr = ((struct sockaddr_in *)aip->ai_addr)->sin_addr;
  234. break;
  235. }
  236. }
  237. freeaddrinfo(ailist);
  238. }
  239. }
  240. #endif
  241. }
  242. void TC_Socket::parseAddr(const string &host, struct in6_addr &stSinAddr)
  243. {
  244. int iRet = inet_pton(AF_INET6, host.c_str(), &stSinAddr);
  245. if(iRet < 0)
  246. {
  247. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::parseAddr] inet_pton(" + host + ") error");
  248. }
  249. else if(iRet == 0)
  250. {
  251. struct addrinfo* info = 0;
  252. int retry = 5;
  253. struct addrinfo hints = { 0 };
  254. hints.ai_family=AF_INET6;
  255. hints.ai_socktype=SOCK_STREAM;
  256. hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
  257. hints.ai_protocol=IPPROTO_TCP;
  258. int rs = 0;
  259. do
  260. {
  261. rs = getaddrinfo(host.c_str(), 0, &hints, &info);
  262. }
  263. while(info == 0 && rs == EAI_AGAIN && --retry >= 0);
  264. if(rs != 0)
  265. {
  266. ostringstream os;
  267. os << "DNSException ex:(" << TC_Exception::parseError(TC_Exception::getSystemCode()) << ")" << rs << ":" << host << ":" << __FILE__ << ":" << __LINE__;
  268. if(info != NULL)
  269. {
  270. freeaddrinfo(info);
  271. }
  272. throw TC_Socket_Exception(os.str());
  273. }
  274. assert(info != NULL);
  275. memcpy(&stSinAddr, info->ai_addr, sizeof(stSinAddr));
  276. freeaddrinfo(info);
  277. }
  278. }
  279. void TC_Socket::parseAddr(const addr_type& addr, string& host, uint16_t &port)
  280. {
  281. int iDomain;
  282. sockaddr_in6 *addr6;
  283. sockaddr_in *addr4;
  284. if (addr.second == sizeof(sizeof(struct sockaddr_in6)))
  285. {
  286. iDomain = AF_INET6;
  287. addr6 = (sockaddr_in6 *) addr.first.get();
  288. }
  289. else
  290. {
  291. iDomain = AF_INET;
  292. addr4 = (sockaddr_in *) addr.first.get();
  293. }
  294. char sAddr[INET6_ADDRSTRLEN] = "\0";
  295. inet_ntop(iDomain, (AF_INET6 == iDomain) ? (void *) &(addr6->sin6_addr) : (void *) &addr4->sin_addr, sAddr, sizeof(sAddr));
  296. host = sAddr;
  297. port = (AF_INET6 == iDomain) ? ntohs(addr6->sin6_port) : ntohs(addr4->sin_port);
  298. }
  299. TC_Socket::addr_type TC_Socket::createSockAddr(const char *str)
  300. {
  301. TC_Socket::addr_type addr;
  302. if (TC_Socket::addressIsIPv6(str))
  303. {
  304. addr.first.reset( (sockaddr *)new sockaddr_in6());
  305. addr.second = sizeof(struct sockaddr_in6);
  306. }
  307. else
  308. {
  309. addr.first.reset((sockaddr *) new sockaddr_in());
  310. addr.second = sizeof(struct sockaddr_in);
  311. }
  312. return addr;
  313. }
  314. void TC_Socket::parseAddrWithPort(const string& host, int port, struct sockaddr_in& addr)
  315. {
  316. memset(&addr, 0, sizeof(struct sockaddr_in));
  317. addr.sin_family = AF_INET;
  318. addr.sin_port = htons(port);
  319. if (host == "" || host == "0.0.0.0" || host == "*")
  320. {
  321. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  322. }
  323. else {
  324. parseAddr(host, addr.sin_addr);
  325. }
  326. }
  327. void TC_Socket::parseAddrWithPort(const string& host, int port, struct sockaddr_in6& addr)
  328. {
  329. memset(&addr, 0, sizeof(struct sockaddr_in6));
  330. addr.sin6_family = AF_INET6;
  331. addr.sin6_port = htons(port);
  332. if (host == "")
  333. {
  334. addr.sin6_addr = in6addr_any;
  335. }
  336. else {
  337. parseAddr(host, addr.sin6_addr);
  338. }
  339. }
  340. void TC_Socket::bind(const string &sServerAddr, int port)
  341. {
  342. assert(_iDomain == AF_INET || _iDomain == AF_INET6);
  343. struct sockaddr_in6 bindAddr6;
  344. struct sockaddr_in bindAddr4;
  345. struct sockaddr *bindAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&bindAddr6 : (struct sockaddr *)&bindAddr4;
  346. socklen_t len = (AF_INET6 == _iDomain) ? sizeof(bindAddr6) : sizeof(bindAddr4);
  347. bzero(bindAddr, len);
  348. if (AF_INET6 == _iDomain)
  349. {
  350. parseAddrWithPort(sServerAddr, port, bindAddr6);
  351. }
  352. else
  353. {
  354. parseAddrWithPort(sServerAddr, port, bindAddr4);
  355. }
  356. try
  357. {
  358. bind(bindAddr, len);
  359. }
  360. catch(const std::exception& e)
  361. {
  362. std::cerr << e.what() << ", " << sServerAddr << ":" << port << endl;
  363. throw e;
  364. }
  365. }
  366. void TC_Socket::bind(const struct sockaddr *pstBindAddr, SOCKET_LEN_TYPE iAddrLen)
  367. {
  368. //如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间
  369. int iReuseAddr = 1;
  370. setSockOpt(SO_REUSEADDR, (const void *)&iReuseAddr, sizeof(int), SOL_SOCKET);
  371. if(::bind(_sock, pstBindAddr, iAddrLen) < 0)
  372. {
  373. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::bind] bind error");
  374. }
  375. }
  376. void TC_Socket::close()
  377. {
  378. if (_sock != INVALID_SOCKET)
  379. {
  380. TC_Port::closeSocket(_sock);
  381. // ::close(_sock);
  382. _sock = INVALID_SOCKET;
  383. }
  384. }
  385. int TC_Socket::connectNoThrow(const string &sServerAddr, uint16_t port)
  386. {
  387. assert(_iDomain == AF_INET || _iDomain == AF_INET6);
  388. if (sServerAddr == "")
  389. {
  390. throw TC_Socket_Exception("[TC_Socket::connect] server address is empty error!");
  391. }
  392. struct sockaddr_in6 serverAddr6;
  393. struct sockaddr_in serverAddr4;
  394. struct sockaddr *serverAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&serverAddr6 : (struct sockaddr *)&serverAddr4;
  395. socklen_t len = (AF_INET6 == _iDomain) ? sizeof(serverAddr6) : sizeof(serverAddr4);
  396. bzero(serverAddr, len);
  397. if (AF_INET6 == _iDomain)
  398. {
  399. serverAddr6.sin6_family = _iDomain;
  400. parseAddr(sServerAddr, serverAddr6.sin6_addr);
  401. serverAddr6.sin6_port = htons(port);
  402. }
  403. else
  404. {
  405. serverAddr4.sin_family = _iDomain;
  406. parseAddr(sServerAddr, serverAddr4.sin_addr);
  407. serverAddr4.sin_port = htons(port);
  408. }
  409. return connect(serverAddr, len);
  410. }
  411. int TC_Socket::connectNoThrow(const struct sockaddr* addr)
  412. {
  413. assert(_iDomain == AF_INET || _iDomain == AF_INET6);
  414. return connect(addr, (AF_INET6 == _iDomain) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
  415. }
  416. void TC_Socket::connect(const string &sServerAddr, uint16_t port)
  417. {
  418. int ret = connectNoThrow(sServerAddr, port);
  419. if(ret < 0)
  420. {
  421. THROW_EXCEPTION_SYSCODE(TC_SocketConnect_Exception, "[TC_Socket::connect] connect error");
  422. }
  423. }
  424. int TC_Socket::connect(const struct sockaddr *pstServerAddr, SOCKET_LEN_TYPE serverLen)
  425. {
  426. return ::connect(_sock, pstServerAddr, serverLen);
  427. }
  428. void TC_Socket::listen(int iConnBackLog)
  429. {
  430. if (::listen(_sock, iConnBackLog) < 0)
  431. {
  432. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::listen] listen error");
  433. }
  434. }
  435. int TC_Socket::recv(void *pvBuf, size_t iLen, int iFlag)
  436. {
  437. return ::recv(_sock, (char*)pvBuf, (int)iLen, iFlag);
  438. }
  439. int TC_Socket::send(const void *pvBuf, size_t iLen, int iFlag)
  440. {
  441. return ::send(_sock, (char*)pvBuf, (int)iLen, iFlag);
  442. }
  443. int TC_Socket::recvfrom(void *pvBuf, size_t iLen, string &sFromAddr, uint16_t &iFromPort, int iFlags)
  444. {
  445. int iBytes;
  446. struct sockaddr_in6 stFromAddr6;
  447. struct sockaddr_in stFromAddr4;
  448. struct sockaddr *stFromAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&stFromAddr6 : (struct sockaddr *)&stFromAddr4;
  449. socklen_t iFromLen = (AF_INET6 == _iDomain) ? sizeof(stFromAddr6) : sizeof(stFromAddr4);
  450. bzero(stFromAddr, iFromLen);
  451. iBytes = recvfrom(pvBuf, iLen, stFromAddr, iFromLen, iFlags);
  452. if (iBytes >= 0)
  453. {
  454. char sAddr[INET6_ADDRSTRLEN] = "\0";
  455. inet_ntop(_iDomain, (AF_INET6 == _iDomain) ? (void *)&stFromAddr6.sin6_addr : (void *)&stFromAddr4.sin_addr, sAddr, sizeof(sAddr));
  456. sFromAddr = sAddr;
  457. iFromPort = (AF_INET6 == _iDomain) ? ntohs(stFromAddr6.sin6_port) : ntohs(stFromAddr4.sin_port);
  458. }
  459. return iBytes;
  460. }
  461. int TC_Socket::recvfrom(void *pvBuf, size_t iLen, struct sockaddr *pstFromAddr, SOCKET_LEN_TYPE &iFromLen, int iFlags)
  462. {
  463. return ::recvfrom(_sock, (char*)pvBuf, (int)iLen, iFlags, pstFromAddr, &iFromLen);
  464. }
  465. int TC_Socket::sendto(const void *pvBuf, size_t iLen, const string &sToAddr, uint16_t port, int iFlags)
  466. {
  467. struct sockaddr_in6 toAddr6;
  468. struct sockaddr_in toAddr4;
  469. struct sockaddr *toAddr = (AF_INET6 == _iDomain) ? (struct sockaddr *)&toAddr6 : (struct sockaddr *)&toAddr4;
  470. socklen_t len = (AF_INET6 == _iDomain) ? sizeof(toAddr6) : sizeof(toAddr4);
  471. bzero(toAddr, len);
  472. if (AF_INET6 == _iDomain)
  473. {
  474. toAddr6.sin6_family = _iDomain;
  475. if (sToAddr == "")
  476. {
  477. //toAddr.sin6_addr = in6addr_linklocal_allrouters;
  478. }
  479. else
  480. {
  481. parseAddr(sToAddr, toAddr6.sin6_addr);
  482. }
  483. toAddr6.sin6_port = htons(port);
  484. }
  485. else
  486. {
  487. toAddr4.sin_family = _iDomain;
  488. if (sToAddr == "")
  489. {
  490. toAddr4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
  491. }
  492. else
  493. {
  494. parseAddr(sToAddr, toAddr4.sin_addr);
  495. }
  496. toAddr4.sin_port = htons(port);
  497. }
  498. return sendto(pvBuf, iLen, toAddr, len, iFlags);
  499. }
  500. int TC_Socket::sendto(const void *pvBuf, size_t iLen, struct sockaddr *pstToAddr, SOCKET_LEN_TYPE iToLen, int iFlags)
  501. {
  502. return ::sendto(_sock, (char*)pvBuf, (int)iLen, iFlags, pstToAddr, iToLen);
  503. }
  504. void TC_Socket::shutdown(int iHow)
  505. {
  506. if (::shutdown(_sock, iHow) < 0)
  507. {
  508. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::shutdown] shutdown error");
  509. }
  510. }
  511. void TC_Socket::setblock(bool bBlock)
  512. {
  513. assert(_sock != INVALID_SOCKET);
  514. setblock(_sock, bBlock);
  515. }
  516. int TC_Socket::setSockOpt(int opt, const void *pvOptVal, SOCKET_LEN_TYPE optLen, int level)
  517. {
  518. return setsockopt(_sock, level, opt, (const char*)pvOptVal, optLen);
  519. }
  520. int TC_Socket::getSockOpt(int opt, void *pvOptVal, SOCKET_LEN_TYPE &optLen, int level) const
  521. {
  522. return getsockopt(_sock, level, opt, (char*)pvOptVal, &optLen);
  523. }
  524. void TC_Socket::setNoCloseWait()
  525. {
  526. linger stLinger;
  527. stLinger.l_onoff = 1; //在close socket调用后, 但是还有数据没发送完毕的时候容许逗留
  528. stLinger.l_linger = 0; //容许逗留的时间为0秒
  529. if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1)
  530. {
  531. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setNoCloseWait] error");
  532. }
  533. }
  534. void TC_Socket::setReuseAddr()
  535. {
  536. int iReuseAddr = 1;
  537. if (setSockOpt(SO_REUSEADDR, (const void *) &iReuseAddr, sizeof(int), SOL_SOCKET) == -1)
  538. {
  539. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setReuseAddr] error");
  540. // throw TC_Socket_Exception("[TC_Socket::setNoCloseWait] error", TC_Exception::getSystemCode());
  541. }
  542. }
  543. void TC_Socket::setCloseWait(int delay)
  544. {
  545. linger stLinger;
  546. stLinger.l_onoff = 1; //在close socket调用后, 但是还有数据没发送完毕的时候容许逗留
  547. stLinger.l_linger = delay; //容许逗留的时间为delay秒
  548. if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1)
  549. {
  550. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setCloseWait] error");
  551. // throw TC_Socket_Exception("[TC_Socket::setCloseWait] error", TC_Exception::getSystemCode());
  552. }
  553. }
  554. void TC_Socket::setCloseWaitDefault()
  555. {
  556. linger stLinger;
  557. stLinger.l_onoff = 0;
  558. stLinger.l_linger = 0;
  559. if(setSockOpt(SO_LINGER, (const void *)&stLinger, sizeof(linger), SOL_SOCKET) == -1)
  560. {
  561. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setCloseWaitDefault] error");
  562. }
  563. }
  564. void TC_Socket::setTcpNoDelay()
  565. {
  566. int flag = 1;
  567. if(setSockOpt(TCP_NODELAY, (char*)&flag, int(sizeof(int)), IPPROTO_TCP) == -1)
  568. {
  569. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setTcpNoDelay] error");
  570. }
  571. }
  572. void TC_Socket::setKeepAlive()
  573. {
  574. int flag = 1;
  575. if(setSockOpt(SO_KEEPALIVE, (char*)&flag, int(sizeof(int)), SOL_SOCKET) == -1)
  576. {
  577. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setKeepAlive] error");
  578. }
  579. }
  580. void TC_Socket::setSendBufferSize(int sz)
  581. {
  582. if(setSockOpt(SO_SNDBUF, (char*)&sz, int(sizeof(int)), SOL_SOCKET) == -1)
  583. {
  584. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setKeepsetSendBufferSizeAlive] error");
  585. }
  586. }
  587. int TC_Socket::getSendBufferSize() const
  588. {
  589. int sz;
  590. SOCKET_LEN_TYPE len = sizeof(sz);
  591. if (getSockOpt(SO_SNDBUF, (void*)&sz, len, SOL_SOCKET) == -1 || len != sizeof(sz))
  592. {
  593. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getSendBufferSize] error");
  594. }
  595. return sz;
  596. }
  597. void TC_Socket::setRecvBufferSize(int sz)
  598. {
  599. if(setSockOpt(SO_RCVBUF, (char*)&sz, int(sizeof(int)), SOL_SOCKET) == -1)
  600. {
  601. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setRecvBufferSize] error");
  602. }
  603. }
  604. int TC_Socket::getRecvBufferSize() const
  605. {
  606. int sz;
  607. SOCKET_LEN_TYPE len = sizeof(sz);
  608. if (getSockOpt(SO_RCVBUF, (void*)&sz, len, SOL_SOCKET) == -1 || len != sizeof(sz))
  609. {
  610. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::getRecvBufferSize] error");
  611. }
  612. return sz;
  613. }
  614. void TC_Socket::ignoreSigPipe() {
  615. #ifdef TARGET_PLATFORM_IOS
  616. int set = 1;
  617. if (setSockOpt(SO_NOSIGPIPE, (char*)&set, int(sizeof(int)), SOL_SOCKET) == -1)
  618. {
  619. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::ignoreSigPipe] error");
  620. }
  621. #endif
  622. }
  623. void TC_Socket::setblock(SOCKET_TYPE fd, bool bBlock)
  624. {
  625. #if TARGET_PLATFORM_LINUX||TARGET_PLATFORM_IOS
  626. int val = 0;
  627. if ((val = fcntl(fd, F_GETFL, 0)) == -1)
  628. {
  629. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] fcntl [F_GETFL] error");
  630. // throw TC_Socket_Exception("[TC_Socket::setblock] fcntl [F_GETFL] error", TC_Exception::getSystemCode());
  631. }
  632. if (!bBlock)
  633. {
  634. val |= O_NONBLOCK;
  635. }
  636. else
  637. {
  638. val &= ~O_NONBLOCK;
  639. }
  640. if (fcntl(fd, F_SETFL, val) == -1)
  641. {
  642. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] fcntl [F_SETFL] error");
  643. }
  644. #else
  645. unsigned long ul = bBlock ? 0 : 1;
  646. int ret;
  647. ret = ioctlsocket(fd, FIONBIO, (unsigned long *)&ul);
  648. if (ret == SOCKET_ERROR)
  649. {
  650. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::setblock] ioctlsocket [FIONBIO] error");
  651. }
  652. #endif
  653. }
  654. void TC_Socket::createPipe(int fds[2], bool bBlock)
  655. {
  656. int tcp1, tcp2;
  657. sockaddr_in name;
  658. memset(&name, 0, sizeof(name));
  659. name.sin_family = AF_INET;
  660. name.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  661. SOCKET_LEN_TYPE namelen = sizeof(name);
  662. tcp1 = tcp2 = -1;
  663. int tcp = socket(AF_INET, SOCK_STREAM, 0);
  664. if (tcp == -1) {
  665. goto clean;
  666. }
  667. if (::bind(tcp, (sockaddr*)&name, namelen) == -1) {
  668. goto clean;
  669. }
  670. if (::listen(tcp, 5) == -1) {
  671. goto clean;
  672. }
  673. if (getsockname(tcp, (sockaddr*)&name, &namelen) == -1) {
  674. goto clean;
  675. }
  676. tcp1 = socket(AF_INET, SOCK_STREAM, 0);
  677. if (tcp1 == -1) {
  678. goto clean;
  679. }
  680. if (-1 == ::connect(tcp1, (sockaddr*)&name, namelen)) {
  681. goto clean;
  682. }
  683. tcp2 = ::accept(tcp, (sockaddr*)&name, &namelen);
  684. if (tcp2 == -1) {
  685. goto clean;
  686. }
  687. fds[0] = tcp1;
  688. fds[1] = tcp2;
  689. try
  690. {
  691. #ifdef TARGET_PLATFORM_IOS
  692. int set = 1;
  693. setsockopt(tcp1, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
  694. setsockopt(tcp2, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
  695. #endif
  696. setblock(fds[0], bBlock);
  697. setblock(fds[1], bBlock);
  698. }
  699. catch (...)
  700. {
  701. goto clean;
  702. }
  703. // #if TARGET_PLATFORM_LINUX||TARGET_PLATFORM_IOS
  704. // #define closesocket ::close
  705. // #endif
  706. if (TC_Port::closeSocket(tcp) == -1) {
  707. goto clean;
  708. }
  709. return;
  710. clean:
  711. if (tcp != -1) {
  712. TC_Port::closeSocket(tcp);
  713. }
  714. if (tcp2 != -1) {
  715. TC_Port::closeSocket(tcp2);
  716. }
  717. if (tcp1 != -1) {
  718. TC_Port::closeSocket(tcp1);
  719. }
  720. // #if TARGET_PLATFORM_LINUX||TARGET_PLATFORM_IOS
  721. // #undef closesocket
  722. // #endif
  723. THROW_EXCEPTION_SYSCODE(TC_Socket_Exception, "[TC_Socket::createPipe] error");
  724. }
  725. #if TARGET_PLATFORM_LINUX
  726. vector<string> TC_Socket::getLocalHosts(int domain)
  727. {
  728. vector<string> result;
  729. TC_Socket ts;
  730. ts.createSocket(SOCK_STREAM, domain);
  731. int cmd = SIOCGIFCONF;
  732. struct ifconf ifc;
  733. int numaddrs = 10;
  734. int old_ifc_len = 0;
  735. while(true)
  736. {
  737. int bufsize = numaddrs * static_cast<int>(sizeof(struct ifreq));
  738. ifc.ifc_len = bufsize;
  739. ifc.ifc_buf = (char*)malloc(bufsize);
  740. int rs = ioctl(ts.getfd(), cmd, &ifc);
  741. if(rs == -1)
  742. {
  743. free(ifc.ifc_buf);
  744. throw TC_Socket_Exception("[TC_Socket::getLocalHosts] ioctl error", errno);
  745. }
  746. else if(ifc.ifc_len == old_ifc_len)
  747. {
  748. break;
  749. }
  750. else
  751. {
  752. old_ifc_len = ifc.ifc_len;
  753. }
  754. numaddrs += 10;
  755. free(ifc.ifc_buf);
  756. }
  757. numaddrs = ifc.ifc_len / static_cast<int>(sizeof(struct ifreq));
  758. struct ifreq* ifr = ifc.ifc_req;
  759. for(int i = 0; i < numaddrs; ++i)
  760. {
  761. if(ifr[i].ifr_addr.sa_family == AF_INET)
  762. {
  763. struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(&ifr[i].ifr_addr);
  764. if(addr->sin_addr.s_addr != 0)
  765. {
  766. char sAddr[INET_ADDRSTRLEN] = "\0";
  767. inet_ntop(AF_INET, &(*addr).sin_addr, sAddr, sizeof(sAddr));
  768. result.push_back(sAddr);
  769. }
  770. }
  771. else if (ifr[i].ifr_addr.sa_family == AF_INET6)
  772. {
  773. struct sockaddr_in6* addr = reinterpret_cast<struct sockaddr_in6*>(&ifr[i].ifr_addr);
  774. if(!memcmp(&addr->sin6_addr, &in6addr_any, sizeof(addr->sin6_addr)))
  775. {
  776. char sAddr[INET6_ADDRSTRLEN] = "\0";
  777. inet_ntop(AF_INET6, &(*addr).sin6_addr, sAddr, sizeof(sAddr));
  778. result.push_back(sAddr);
  779. }
  780. }
  781. }
  782. free(ifc.ifc_buf);
  783. return result;
  784. }
  785. #elif TARGET_PLATFORM_IOS
  786. vector<string> TC_Socket::getLocalHosts(int domain)
  787. {
  788. vector<string> hosts;
  789. char local[255] = { 0 };
  790. gethostname(local, sizeof(local));
  791. hostent* ph = gethostbyname(local);
  792. if (ph == NULL)
  793. {
  794. return hosts;
  795. }
  796. in_addr addr;
  797. if (ph->h_addrtype == AF_INET)
  798. {
  799. int i = 0;
  800. while (ph->h_addr_list[i] != 0)
  801. {
  802. addr.s_addr = *(u_long*)ph->h_addr_list[i++];
  803. hosts.emplace_back(inet_ntoa(addr));
  804. }
  805. }
  806. else
  807. {
  808. // unsupport AF_INET6 ...
  809. return hosts;
  810. }
  811. return hosts;
  812. }
  813. #endif
  814. #if TARGET_PLATFORM_WINDOWS
  815. vector<string> TC_Socket::getLocalHosts(int domain)
  816. {
  817. vector<string> hosts;
  818. WORD wVersionRequested = MAKEWORD(2, 2);
  819. WSADATA wsaData;
  820. if (WSAStartup(wVersionRequested, &wsaData) != 0)
  821. {
  822. return hosts;
  823. }
  824. char local[255] = { 0 };
  825. gethostname(local, sizeof(local));
  826. hostent* ph = gethostbyname(local);
  827. if (ph == NULL)
  828. {
  829. return hosts;
  830. }
  831. in_addr addr;
  832. if (ph->h_addrtype == AF_INET)
  833. {
  834. int i = 0;
  835. while (ph->h_addr_list[i] != 0)
  836. {
  837. addr.s_addr = *(u_long*)ph->h_addr_list[i++];
  838. hosts.emplace_back(inet_ntoa(addr));
  839. }
  840. }
  841. else
  842. {
  843. // unsupport AF_INET6 ...
  844. return hosts;
  845. }
  846. WSACleanup();
  847. return hosts;
  848. }
  849. #endif
  850. bool TC_Socket::isPending()
  851. {
  852. #if TARGET_PLATFORM_WINDOWS
  853. return TC_Exception::getSystemCode() == WSAEWOULDBLOCK;
  854. #else
  855. return TC_Exception::getSystemCode() == EAGAIN;
  856. #endif
  857. }
  858. bool TC_Socket::isInProgress()
  859. {
  860. #if TARGET_PLATFORM_WINDOWS
  861. return TC_Exception::getSystemCode() == WSAEWOULDBLOCK;
  862. #else
  863. return TC_Exception::getSystemCode() == EINPROGRESS;
  864. #endif
  865. }
  866. }