愿你出走半生,归来仍是少年

^_^

怀揣梦想,永不放弃

导航

X86 Socket 通信

  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]======\n", 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 }

 

posted on 2016-03-21 17:04  Jeffrey.Downhouse  阅读(300)  评论(0编辑  收藏  举报

运筹帷幄之中 | 决胜千里之外