net.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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 <string.h>
  13. #include "utils/Log.h"
  14. namespace net {
  15. static int NonBlockConnect(int fd, const struct sockaddr* ai_addr,
  16. socklen_t ai_addrlen, int out_time_seconds) {
  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 = out_time_seconds;
  43. timeout.tv_usec = 0;
  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. LOGD("send msg : %s",p);
  90. while (true) {
  91. tmp = send(sock_fd, p, total, 0);
  92. if (tmp < 0) {
  93. // 当send收到信号时,可以继续写,但这里返回-1.
  94. if (errno == EINTR) {
  95. usleep(1000 * 100);
  96. continue;
  97. }
  98. // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满,
  99. // 在这里做延时后再重试.
  100. if (errno == EAGAIN) {
  101. usleep(1000 * 100);
  102. continue;
  103. }
  104. return -1;
  105. }
  106. if ((size_t) tmp == total) {
  107. LOGD("send success");
  108. return buflen;
  109. }
  110. total -= tmp;
  111. p += tmp;
  112. }
  113. return tmp;
  114. }
  115. class TcpClientConn: public Conn {
  116. public:
  117. bool Connect(std::string host, std::string port) {
  118. int status;
  119. int socketfd = -1;
  120. struct addrinfo host_info; // The struct that getaddrinfo() fills up with data.
  121. struct addrinfo * host_info_list = NULL;
  122. memset(&host_info, 0, sizeof host_info);
  123. host_info.ai_family = AF_UNSPEC; // IP version not specified. Can be both.
  124. host_info.ai_socktype = SOCK_STREAM; // Use SOCK_STREAM for TCP or SOCK_DGRAM for UDP.
  125. LOGD("getaddrinfo");
  126. status = getaddrinfo(host.c_str(), port.c_str(), &host_info,
  127. &host_info_list);
  128. if (status != 0) {
  129. LOGD("ERROR: Hostname could not be resolved");
  130. return false;
  131. }
  132. LOGD("socket init");
  133. socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
  134. host_info_list->ai_protocol);
  135. if (socketfd == -1) {
  136. LOGE("ERROR: Could not open socket");
  137. freeaddrinfo(host_info_list);
  138. return false;
  139. }
  140. #if 0
  141. status = ::connect(socketfd, host_info_list_->ai_addr,
  142. host_info_list_->ai_addrlen);
  143. #else
  144. status = NonBlockConnect(socketfd, host_info_list->ai_addr,
  145. host_info_list->ai_addrlen, 10);
  146. #endif
  147. if (status == -1) {
  148. LOGE("ERROR: Could not connect");
  149. freeaddrinfo(host_info_list);
  150. close(socketfd);
  151. return false;
  152. }
  153. sock_ = socketfd;
  154. host_info_list_ = host_info_list;
  155. LOGD("connect %s success!\n", host.c_str());
  156. return true;
  157. }
  158. virtual int Write(byte* bytes, int bytes_len) {
  159. if (sock_ < 0) {
  160. return -1;
  161. }
  162. return Send(sock_, bytes, bytes_len);
  163. }
  164. virtual int Read(byte* buffer, int buffer_len, int timeout_millisecond) {
  165. if (sock_ < 0) {
  166. //没有连接
  167. return -1;
  168. }
  169. struct pollfd fd;
  170. fd.fd = sock_;
  171. fd.events = POLLIN;
  172. int ret = poll(&fd, 1, timeout_millisecond);
  173. switch (ret) {
  174. case -1:
  175. //LOGD("poll error"); // Error
  176. Close();
  177. return -1;
  178. break;
  179. case 0:
  180. // Timeout
  181. //LOGD("select read timeouot");
  182. return net::E_TIMEOUT;
  183. break;
  184. default: {
  185. int recv_bytes = recv(sock_, buffer, buffer_len, 0);
  186. if (recv_bytes == 0) {
  187. //连接已关闭
  188. LOGD("recv 0, close it");
  189. Close();
  190. return 0;
  191. } else if (recv_bytes < 0) {
  192. //添加错误处理
  193. if ((errno == EINTR) || (errno == EWOULDBLOCK) || (errno == EAGAIN)) {
  194. //继续recv
  195. LOGD("eagain");
  196. } else {
  197. LOGD("disconnect %d", errno);
  198. Close();
  199. return -1;
  200. }
  201. } else if (recv_bytes > 0) {
  202. return recv_bytes;
  203. }
  204. }
  205. break;
  206. }
  207. return -1;
  208. }
  209. virtual void Close() {
  210. if (sock_ >= 0) {
  211. LOGD("SocketClient close socket...\n");
  212. freeaddrinfo(host_info_list_);
  213. host_info_list_ = NULL;
  214. close(sock_);
  215. sock_ = -1;
  216. }
  217. }
  218. virtual Addr LocalAddr() {
  219. return Addr();
  220. }
  221. virtual Addr RemoteAddr() {
  222. return Addr();
  223. }
  224. TcpClientConn() {
  225. sock_ = -1;
  226. host_info_list_ = NULL;
  227. }
  228. virtual ~TcpClientConn() {
  229. Close();
  230. }
  231. private:
  232. int sock_;
  233. struct addrinfo *host_info_list_;
  234. };
  235. class UdpConn : public Conn {
  236. public:
  237. bool Initialize(std::string host, std::string port) {
  238. if ((sock_ = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  239. LOGD("socket fail\n");
  240. return false;
  241. }
  242. #if 1
  243. //设置为广播类型,
  244. const int opt = 1;
  245. int nb = 0;
  246. nb = setsockopt(sock_, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
  247. if(nb == -1) {
  248. LOGD("set socket error...");
  249. return false;
  250. }
  251. #endif
  252. #if 1
  253. /*设置套接字为非阻塞*/
  254. int flags = fcntl(sock_, F_GETFL, 0);
  255. if (flags < 0) {
  256. LOGD("Get flags error:%s", strerror(errno));
  257. return -1;
  258. }
  259. flags |= O_NONBLOCK;
  260. if (fcntl(sock_, F_SETFL, flags) < 0) {
  261. LOGD("Set flags error:%s", strerror(errno));
  262. return -1;
  263. }
  264. #endif
  265. memset(&remote_addr_, 0, sizeof(remote_addr_));
  266. remote_addr_.sin_family = AF_INET;
  267. remote_addr_.sin_port = htons(atoi(port.c_str()));
  268. remote_addr_.sin_addr.s_addr = inet_addr(host.c_str());
  269. return true;
  270. }
  271. virtual int Write(byte* bytes, int bytes_len) {
  272. if (sock_ < 0) {
  273. return -1;
  274. }
  275. return sendto(sock_, bytes, bytes_len, 0, (sockaddr*)&remote_addr_, sizeof(remote_addr_));
  276. }
  277. /**
  278. * timeout: 超时时间 毫秒
  279. * return >0 读到数据
  280. * =0 已关闭
  281. * -10000 读取超时
  282. * 其他 出错
  283. */
  284. virtual int Read(byte* buffer, int buffer_len, int timeout_millisecond) {
  285. if (sock_ < 0) {
  286. //没有连接
  287. return -1;
  288. }
  289. struct pollfd fd;
  290. fd.fd = sock_;
  291. fd.events = POLLIN;
  292. int ret = poll(&fd, 1, timeout_millisecond);
  293. switch (ret) {
  294. case -1:
  295. //LOGD("poll error"); // Error
  296. Close();
  297. return -1;
  298. break;
  299. case 0:
  300. // Timeout
  301. //LOGD("select read timeouot");
  302. return net::E_TIMEOUT;
  303. break;
  304. default: {
  305. socklen_t addr_len = sizeof(remote_addr_);
  306. int recv_bytes = recvfrom(sock_, buffer, buffer_len, 0, (sockaddr*)&remote_addr_, &addr_len);
  307. if (recv_bytes == 0) {
  308. //连接已关闭
  309. LOGD("recv 0, close it");
  310. Close();
  311. return 0;
  312. } else if (recv_bytes < 0) {
  313. //添加错误处理
  314. if ((errno == EINTR) || (errno == EWOULDBLOCK) || (errno == EAGAIN)) {
  315. //继续recv
  316. LOGD("eagain");
  317. } else {
  318. LOGD("disconnect %d", errno);
  319. Close();
  320. return -1;
  321. }
  322. } else if (recv_bytes > 0) {
  323. return recv_bytes;
  324. }
  325. }
  326. break;
  327. }
  328. return -1;
  329. }
  330. virtual void Close() {
  331. if (sock_ >= 0) {
  332. LOGD("UdpClient close socket");
  333. close(sock_);
  334. sock_ = -1;
  335. }
  336. }
  337. virtual Addr LocalAddr() {
  338. return Addr();
  339. }
  340. virtual Addr RemoteAddr() {
  341. return Addr();
  342. }
  343. virtual ~UdpConn() {
  344. Close();
  345. }
  346. private:
  347. struct sockaddr_in remote_addr_;
  348. int sock_;
  349. };
  350. /**
  351. * tcp, 192.168.1.1:80
  352. */
  353. Conn* Dial(std::string network, std::string address) {
  354. signal(SIGPIPE,SIG_IGN);
  355. int colon = address.find(':');
  356. if (network.compare("tcp") == 0) {
  357. TcpClientConn* tcp = new TcpClientConn();
  358. LOGD("TCP connect: %s", address.c_str());
  359. tcp->Connect(address.substr(0, colon), address.substr(colon + 1));
  360. return tcp;
  361. } else if (network.compare("udp") == 0) {
  362. UdpConn* udp = new UdpConn();
  363. udp->Initialize(address.substr(0, colon), address.substr(colon + 1));
  364. return udp;
  365. } else {
  366. return NULL;
  367. }
  368. }
  369. } /* namespace net */