net.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. #include "net.h"
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <netdb.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <poll.h>
  8. #include <sys/select.h>
  9. #include <errno.h>
  10. #include <time.h>
  11. #include <signal.h>
  12. #include <errno.h>
  13. #include <string.h>
  14. namespace net {
  15. static int NonBlockConnect(int fd, const struct sockaddr* ai_addr,
  16. socklen_t ai_addrlen, int timeout_millis) {
  17. /*设置套接字为非阻塞*/
  18. int flags = fcntl(fd, F_GETFL, 0);
  19. if (flags < 0) {
  20. LOGD("Get flags error:%s\n", strerror(errno));
  21. return -1;
  22. }
  23. flags |= O_NONBLOCK;
  24. if (fcntl(fd, F_SETFL, flags) < 0) {
  25. LOGD("Set flags error:%s\n", strerror(errno));
  26. return -1;
  27. }
  28. fd_set fdr, fdw;
  29. struct timeval timeout;
  30. int err = 0;
  31. int errlen = sizeof(err);
  32. /*阻塞情况下linux系统默认超时时间为75s*/
  33. int rc = ::connect(fd, ai_addr, ai_addrlen);
  34. if (rc != 0) {
  35. if (errno == EINPROGRESS) {
  36. LOGD("Doing connection.\n");
  37. /*正在处理连接*/
  38. FD_ZERO(&fdr);
  39. FD_ZERO(&fdw);
  40. FD_SET(fd, &fdr);
  41. FD_SET(fd, &fdw);
  42. timeout.tv_sec = timeout_millis/1000;
  43. timeout.tv_usec = (timeout_millis % 1000) * 1000;
  44. rc = select(fd + 1, &fdr, &fdw, NULL, &timeout);
  45. LOGD("rc is: %d\n", rc);
  46. /*select调用失败*/
  47. if (rc < 0) {
  48. LOGD("connect error:%s\n", strerror(errno));
  49. return -1;
  50. }
  51. /*连接超时*/
  52. if (rc == 0) {
  53. LOGD("Connect timeout.\n");
  54. return -1;
  55. }
  56. /*[1] 当连接成功建立时,描述符变成可写,rc=1*/
  57. if (rc == 1 && FD_ISSET(fd, &fdw)) {
  58. LOGD("Connect success\n");
  59. return 0;
  60. }
  61. /*[2] 当连接建立遇到错误时,描述符变为即可读,也可写,rc=2 遇到这种情况,可调用getsockopt函数*/
  62. if (rc == 2) {
  63. if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, (socklen_t*)&errlen) == -1) {
  64. LOGD("getsockopt(SO_ERROR): %s", strerror(errno));
  65. return -1;
  66. }
  67. if (err) {
  68. errno = err;
  69. LOGD("connect error:%s\n", strerror(errno));
  70. return -1;
  71. }
  72. }
  73. }
  74. LOGD("connect failed, error:%s.\n", strerror(errno));
  75. return -1;
  76. }
  77. return rc;
  78. }
  79. static int Send(int sock_fd, const byte* buffer, size_t buflen) {
  80. if (buflen <= 0) {
  81. return 0;
  82. }
  83. if (buffer == NULL) {
  84. return 0;
  85. }
  86. size_t tmp;
  87. size_t total = buflen;
  88. const unsigned char *p = buffer;
  89. while (true) {
  90. tmp = send(sock_fd, p, total, 0);
  91. if (tmp < 0) {
  92. // 当send收到信号时,可以继续写,但这里返回-1.
  93. if (errno == EINTR) {
  94. usleep(1000 * 100);
  95. continue;
  96. }
  97. // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满,
  98. // 在这里做延时后再重试.
  99. if (errno == EAGAIN) {
  100. usleep(1000 * 100);
  101. continue;
  102. }
  103. return -1;
  104. }
  105. if ((size_t) tmp == total) {
  106. // LOGD("send success");
  107. return buflen;
  108. }
  109. total -= tmp;
  110. p += tmp;
  111. }
  112. return tmp;
  113. }
  114. class TcpClientConn: public Conn {
  115. public:
  116. bool Connect(std::string host, std::string port, long timeout_millis) {
  117. int status;
  118. int socketfd = -1;
  119. struct addrinfo host_info; // The struct that getaddrinfo() fills up with data.
  120. struct addrinfo * host_info_list = NULL;
  121. memset(&host_info, 0, sizeof host_info);
  122. host_info.ai_family = AF_UNSPEC; // IP version not specified. Can be both.
  123. host_info.ai_socktype = SOCK_STREAM; // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP.
  124. LOGD("getaddrinfo");
  125. status = getaddrinfo(host.c_str(), port.c_str(), &host_info,
  126. &host_info_list);
  127. if (status != 0) {
  128. LOGD("ERROR: Hostname could not be resolved");
  129. return false;
  130. }
  131. LOGD("socket init");
  132. socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
  133. host_info_list->ai_protocol);
  134. if (socketfd == -1) {
  135. LOGE("ERROR: Could not open socket");
  136. freeaddrinfo(host_info_list);
  137. return false;
  138. }
  139. #if 0
  140. status = ::connect(socketfd, host_info_list_->ai_addr,
  141. host_info_list_->ai_addrlen);
  142. #else
  143. status = NonBlockConnect(socketfd, host_info_list->ai_addr,
  144. host_info_list->ai_addrlen, timeout_millis);
  145. #endif
  146. if (status == -1) {
  147. LOGE("ERROR: Could not connect");
  148. freeaddrinfo(host_info_list);
  149. close(socketfd);
  150. return false;
  151. }
  152. sock_ = socketfd;
  153. host_info_list_ = host_info_list;
  154. LOGD("connect %s success!\n", host.c_str());
  155. return true;
  156. }
  157. virtual int Write(byte* bytes, int bytes_len) {
  158. if (sock_ < 0) {
  159. return -1;
  160. }
  161. return Send(sock_, bytes, bytes_len);
  162. }
  163. virtual int Read(byte* buffer, int buffer_len, int timeout) {
  164. if (sock_ < 0) {
  165. //没有连接
  166. return -1;
  167. }
  168. struct pollfd fd;
  169. fd.fd = sock_;
  170. fd.events = POLLIN;
  171. int ret = poll(&fd, 1, 1000); // 1 second for timeout
  172. switch (ret) {
  173. case -1:
  174. //LOGD("poll error"); // Error
  175. Close();
  176. return -1;
  177. break;
  178. case 0:
  179. // Timeout
  180. //LOGD("select read timeouot");
  181. return net::E_TIMEOUT;
  182. break;
  183. default: {
  184. int recv_bytes = recv(sock_, buffer, buffer_len, 0);
  185. if (recv_bytes == 0) {
  186. //连接已关闭
  187. LOGD("recv 0, close it");
  188. Close();
  189. return 0;
  190. } else if (recv_bytes < 0) {
  191. //添加错误处理
  192. if ((errno == EINTR) || (errno == EWOULDBLOCK) || (errno == EAGAIN)) {
  193. //继续recv
  194. LOGD("eagain");
  195. } else {
  196. LOGD("disconnect %d", errno);
  197. Close();
  198. return -1;
  199. }
  200. } else if (recv_bytes > 0) {
  201. return recv_bytes;
  202. }
  203. }
  204. break;
  205. }
  206. return -1;
  207. }
  208. virtual void Close() {
  209. if (sock_ >= 0) {
  210. LOGD("SocketClient close socket...\n");
  211. freeaddrinfo(host_info_list_);
  212. host_info_list_ = NULL;
  213. close(sock_);
  214. sock_ = -1;
  215. }
  216. }
  217. virtual Addr LocalAddr() {
  218. return Addr();
  219. }
  220. virtual Addr RemoteAddr() {
  221. return Addr();
  222. }
  223. TcpClientConn() {
  224. sock_ = -1;
  225. host_info_list_ = NULL;
  226. }
  227. virtual ~TcpClientConn() {
  228. Close();
  229. }
  230. private:
  231. int sock_;
  232. struct addrinfo *host_info_list_;
  233. };
  234. class UdpConn : public Conn {
  235. public:
  236. bool Initialize(std::string host, std::string port) {
  237. if ((sock_ = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  238. LOGD("socket fail\n");
  239. return false;
  240. }
  241. #if 0
  242. //设置为广播类型,
  243. const int opt = 1;
  244. int nb = 0;
  245. nb = setsockopt(sock_, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
  246. if(nb == -1) {
  247. LOGD("set socket error...");
  248. return false;
  249. }
  250. #endif
  251. #if 0
  252. /*设置套接字为非阻塞*/
  253. int flags = fcntl(sock_, F_GETFL, 0);
  254. if (flags < 0) {
  255. LOGD("Get flags error:%s", strerror(errno));
  256. return -1;
  257. }
  258. flags |= O_NONBLOCK;
  259. if (fcntl(sock_, F_SETFL, flags) < 0) {
  260. LOGD("Set flags error:%s", strerror(errno));
  261. return -1;
  262. }
  263. #endif
  264. memset(&remote_addr_, 0, sizeof(remote_addr_));
  265. remote_addr_.sin_family = AF_INET;
  266. remote_addr_.sin_port = htons(atoi(port.c_str()));
  267. remote_addr_.sin_addr.s_addr = inet_addr(host.c_str());
  268. return true;
  269. }
  270. virtual int Write(byte* bytes, int bytes_len) {
  271. if (sock_ < 0) {
  272. return -1;
  273. }
  274. return sendto(sock_, bytes, bytes_len, 0, (sockaddr*)&remote_addr_, sizeof(remote_addr_));
  275. }
  276. /**
  277. * timeout: 超时时间 毫秒
  278. * return >0 读到数据
  279. * =0 已关闭
  280. * -10000 读取超时
  281. * 其他 出错
  282. */
  283. virtual int Read(byte* buffer, int buffer_len, int timeout) {
  284. if (sock_ < 0) {
  285. //没有连接
  286. return -1;
  287. }
  288. struct pollfd fd;
  289. fd.fd = sock_;
  290. fd.events = POLLIN;
  291. int ret = poll(&fd, 1, timeout); // 1 second for timeout
  292. switch (ret) {
  293. case -1:
  294. //LOGD("poll error"); // Error
  295. Close();
  296. return -1;
  297. break;
  298. case 0:
  299. // Timeout
  300. //LOGD("select read timeouot");
  301. return net::E_TIMEOUT;
  302. break;
  303. default: {
  304. socklen_t addr_len = sizeof(remote_addr_);
  305. int recv_bytes = recvfrom(sock_, buffer, buffer_len, 0, (sockaddr*)&remote_addr_, &addr_len);
  306. if (recv_bytes == 0) {
  307. //连接已关闭
  308. LOGD("recv 0, close it");
  309. Close();
  310. return 0;
  311. } else if (recv_bytes < 0) {
  312. //添加错误处理
  313. if ((errno == EINTR) || (errno == EWOULDBLOCK) || (errno == EAGAIN)) {
  314. //继续recv
  315. LOGD("eagain");
  316. } else {
  317. LOGD("disconnect %d", errno);
  318. Close();
  319. return -1;
  320. }
  321. } else if (recv_bytes > 0) {
  322. return recv_bytes;
  323. }
  324. }
  325. break;
  326. }
  327. return -1;
  328. }
  329. virtual void Close() {
  330. if (sock_ >= 0) {
  331. // LOGD("UdpClient close socket");
  332. close(sock_);
  333. sock_ = -1;
  334. }
  335. }
  336. virtual Addr LocalAddr() {
  337. return Addr();
  338. }
  339. virtual Addr RemoteAddr() {
  340. return Addr();
  341. }
  342. virtual ~UdpConn() {
  343. Close();
  344. }
  345. private:
  346. struct sockaddr_in remote_addr_;
  347. int sock_;
  348. };
  349. /**
  350. * tcp, 192.168.1.1:80
  351. */
  352. Conn* Dial(const std::string &network, const std::string &address, long timeout_millis) {
  353. signal(SIGPIPE,SIG_IGN);
  354. int colon = address.find(':');
  355. if (network.compare("tcp") == 0) {
  356. TcpClientConn* tcp = new TcpClientConn();
  357. bool r = tcp->Connect(address.substr(0, colon), address.substr(colon + 1), timeout_millis);
  358. if (r) {
  359. return tcp;
  360. }
  361. delete tcp;
  362. return NULL;
  363. } else if (network.compare("udp") == 0) {
  364. UdpConn* udp = new UdpConn();
  365. udp->Initialize(address.substr(0, colon), address.substr(colon + 1));
  366. return udp;
  367. } else {
  368. return NULL;
  369. }
  370. }
  371. } /* namespace net */