1 struct txd_socket_handler_t { 2 int fd; 3 }; 4 5 txd_socket_handler_t *txd_tcp_socket_create() { 6 txd_socket_handler_t *sock = (txd_socket_handler_t*)txd_malloc(sizeof(txd_socket_handler_t)); 7 return sock; 8 } 9 10 int32_t txd_tcp_socket_destroy(txd_socket_handler_t *sock) { 11 if (sock) { 12 txd_free(sock); 13 } 14 return 0; 15 } 16 17 int32_t txd_tcp_connect(txd_socket_handler_t *sock, uint8_t *ip, uint16_t port, uint32_t timeout_ms) { 18 struct sockaddr_in addr; 19 struct timeval tv; 20 fd_set wfds; 21 int retval; 22 socklen_t optlen; 23 tv.tv_sec = timeout_ms / 1000; 24 tv.tv_usec = (timeout_ms % 1000) * 1000; 25 memset(&addr, 0, sizeof(addr)); 26 addr.sin_family = AF_INET; 27 addr.sin_port = htons(port); 28 inet_pton(AF_INET, (char *)ip, &addr.sin_addr); 29 30 // 创建socket,并设置为非阻塞(阻塞也是可以的) 31 sock->fd = socket(AF_INET, SOCK_STREAM, 0); 32 fcntl(sock->fd, F_SETFL, fcntl(sock->fd, F_GETFL) | O_NONBLOCK); 33 34 // 尝试连接,返回0表示连接成功,否则判断errno, 35 // 如果errno被设为EINPROGRESS,表示connect仍旧在进行 36 if (connect(sock->fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { 37 return 0; 38 } 39 if (errno != EINPROGRESS) { 40 return -1; 41 } 42 43 FD_ZERO(&wfds); 44 FD_SET(sock->fd, &wfds); 45 46 // 设置timeout,判断socket是否可写,如果可写, 47 // 则用getsockopt得到error的值,若error值为0,表示connect成功 48 retval = select(sock->fd + 1, NULL, &wfds, NULL, &tv); 49 if (retval <= 0) { 50 return -1; 51 } 52 optlen = sizeof(int); 53 if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &retval, &optlen) < 0) { 54 return -1; 55 } 56 if (0 == retval) { 57 return 0; 58 } 59 60 return -1; 61 } 62 63 int32_t txd_tcp_disconnect(txd_socket_handler_t *sock) { 64 close(sock->fd); 65 return 0; 66 } 67 68 int32_t txd_tcp_recv(txd_socket_handler_t *sock, uint8_t *buf, uint32_t len, uint32_t timeout_ms) { 69 struct timeval tv; 70 fd_set rfds; 71 int retval; 72 tv.tv_sec = timeout_ms / 1000; 73 tv.tv_usec = (timeout_ms % 1000) * 1000; 74 FD_ZERO(&rfds); 75 FD_SET(sock->fd, &rfds); 76 77 retval = select(sock->fd + 1, &rfds, NULL, NULL, &tv); 78 if (retval < 0) { 79 return -1; 80 } 81 else if (0 == retval) { 82 return 0; 83 } 84 85 // 不能保证全部读完,需要在上一层根据自己的协议做缓存 86 retval = recv(sock->fd, buf, len, 0); 87 if (retval <= 0 && errno != 0) { 88 printf("========recv: retval[%d], errno[%d]====== ", retval, errno); 89 return -1; 90 } 91 return retval; 92 } 93 94 int32_t txd_tcp_send(txd_socket_handler_t *sock, uint8_t *buf, uint32_t len, uint32_t timeout_ms) { 95 struct timeval tv; 96 fd_set wfds; 97 int retval; 98 tv.tv_sec = timeout_ms / 1000; 99 tv.tv_usec = (timeout_ms % 1000) * 1000; 100 FD_ZERO(&wfds); 101 FD_SET(sock->fd, &wfds); 102 103 retval = select(sock->fd + 1, NULL, &wfds, NULL, &tv); 104 if (retval < 0) { 105 return -1; 106 } 107 else if (0 == retval) { 108 return 0; 109 } 110 111 // 尽量将数据全部写到发送缓冲区 112 uint32_t totlen = 0, n = len; 113 while (totlen < n) { 114 retval = send(sock->fd, buf + totlen, n - totlen, 0); 115 if (retval < 0) { 116 if (errno == EAGAIN || errno == EWOULDBLOCK) { 117 continue; // 发送缓冲区阻塞,选择continue或者break 118 } 119 else if (errno == EINTR) { // 中断错误,继续写 120 continue; 121 } 122 return -1; 123 } 124 totlen += retval; 125 } 126 return totlen; 127 }