美文网首页
使用TCP收发消息需要处理的常见问题

使用TCP收发消息需要处理的常见问题

作者: 漫游之光 | 来源:发表于2020-08-15 14:35 被阅读0次

    要实现服务器和客户端之间完整的收发消息,需要处理以下的几个问题。

    粘包半包问题

    粘包就是一次从socket缓冲区中读取到的数据不止一条消息。半包就是一次从socket缓冲区读取的数据只是一条消息的部分。

    要解决粘包半包的问题,常用的方法有长度信息法、固定长度法和结束符号法。一般的游戏开发中使用的长度信息法。

    长度信息法在要发送的信息前面,加上一个固定长度的信息长度信息,解析的时候,先读出这个固定长度的信息数据,然后读取信息长度的数据。可见,这个方法的核心是实现一个能从socket缓冲区读取指定长度数据的函数。

    从socket缓冲区中读取指定长度的数据,可以参考《unix网络编程》中的readn函数。

    ssize_t                     /* Read "n" bytes from a descriptor. */
    readn(int fd, void *vptr, size_t n)
    {
        size_t  nleft;
        ssize_t nread;
        char    *ptr;
    
        ptr = vptr;
        nleft = n;
        while (nleft > 0) {
            if ( (nread = read(fd, ptr, nleft)) < 0) {
                if (errno == EINTR)
                    nread = 0;      /* and call read() again */
                else
                    return(-1);
            } else if (nread == 0)
                break;              /* EOF */
    
            nleft -= nread;
            ptr   += nread;
        }
        return(n - nleft);      /* return >= 0 */
    }
    /* end readn */
    

    不完整发送问题

    当socket的缓冲区满了的时候,再往缓冲区写数据,写入的数据可能小于要发送的数据。如果不对这种情况进行处理,那发送的数据就可能不完整。因此,我们需要一个向缓冲区写入固定长度数据的函数,同样,我们也可以参考《UNIX网络编程》中的写法。

    ssize_t                     /* Write "n" bytes to a descriptor. */
    writen(int fd, const void *vptr, size_t n)
    {
        size_t      nleft;
        ssize_t     nwritten;
        const char  *ptr;
    
        ptr = vptr;
        nleft = n;
        while (nleft > 0) {
            if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
                if (nwritten < 0 && errno == EINTR)
                    nwritten = 0;       /* and call write() again */
                else
                    return(-1);         /* error */
            }
    
            nleft -= nwritten;
            ptr   += nwritten;
        }
        return(n);
    }
    /* end writen */
    

    大端小端问题

    因为消息前面有一个表示长度的数字,而数字的表示有大端小端之分,要处理这个问题,只需要规定传输的数字是大端表示还是小端表示。然后,在传输的时候进行判断,如果和传输的表示方式不同,进行转换即可。在收到数字的时候,使用自定义的函数来解析这个数字。

    连接断开的问题

    游戏开发中,客户端通常要和服务器保持TCP连接,这时候,就需要处理连接断开问题了。当发送消息的时候,需要检查连接是否正常。关闭的时候,要检查缓冲区的数据是否已经发送完毕,要等数据发送完毕才能关闭。

    我对这方面不是很熟,先写这么多吧。

    相关文章

      网友评论

          本文标题:使用TCP收发消息需要处理的常见问题

          本文链接:https://www.haomeiwen.com/subject/srrsdktx.html