zoukankan      html  css  js  c++  java
  • 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]======
    ", 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 }
    当你坚持做一件完全正确的事情,有可能在很长一段时间内,你的价值都是零。
  • 相关阅读:
    Python服务Debian打包新思路
    小议Python3的原生协程机制
    推送公司今日菜单内容到手机
    Python包管理工具小结
    PAT 1068. 万绿丛中一点红
    PAT 1067. 试密码
    PAT 1066. 图像过滤
    PAT 1065. 单身狗
    PAT 1064. 朋友数
    PAT 1063. 计算谱半径
  • 原文地址:https://www.cnblogs.com/lweleven/p/socket.html
Copyright © 2011-2022 走看看