0

我有一个 TCP 协议服务器-客户端程序。

与很多人不同,我没有收到错误,因为我的发送函数没有发送应有的字节数。我的问题是因为 recv() 函数捕获了一些奇怪的字符。我对它们进行了十六进制转储,它们往往是负数(我猜大于 4 位长)或不是字母数字的。(一直出现的是 \8 = ◘)。

我使用的功能是:

bool Socket::Send(char* msg){
    if ((send(sockfd, msg, strlen(msg), 0)) == SOCKET_ERROR){
        Close();
        return false;
    }
    return true;
}

int Socket::Receive(char* msg, int maxlen){
    int recvResult;
    if ((recvResult = recv(sockfd, msg, maxlen, 0)) == SOCKET_ERROR){
        Close();
    }
    return recvResult;
}

我检查了一下,发送的所有内容都正常。我的意思是,我将它写入一个文件并检查它,它是好的。

还有什么我应该考虑的吗?我究竟做错了什么?

4

2 回答 2

1

与很多人不同,我没有收到错误,因为我的发送函数没有发送应有的字节数。

没有人会得到那个错误,因为它永远不会发生,尽管,因为你没有检查它,你无法断言它没有发生。

我的问题是因为 recv() 函数捕获了一些奇怪的字符。

不会。发生的情况是recv()函数返回的字节数少于请求的字节数,这是因为未指定在非阻塞模式下传输多于一个字节或零字节。您必须循环,直到您读取了您期望的所有数据。

并且您必须注意不要使用接收缓冲区中未在最近一次recv()调用中传输的字节,如其返回值所示。

您几乎可以肯定会打印整个缓冲区,因此您会看到垃圾。它既没有发送也没有接收。

注意如果recv()返回零,您应该关闭套接字。

于 2014-05-17T04:56:32.770 回答
-1

你说你有一个 TCP 协议,你所拥有的不是一个协议,它只是一个 TCP 连接。

为了实现一个协议,您需要发送更多信息,recv() 部分应该(必须)知道将要接收什么。

您需要在缓冲区长度之前发送缓冲区或在缓冲区末尾发送终止字符,这不应该是已发送消息的其余部分的一部分。Line-Feed (10)、Carriage-Return (13) 和 Form-Feed (12) 等字符都是不错的选择。

如果您决定使用终止字符,那么您应该一次读取 (recv) 一个字符,验证这是否是终止指示符。终止字符仅在发送表示文字的字符串时有用,不指示用于发送文件或图像或二进制字符串。

我已经修改了实现缓冲区指示器方法长度的例程:

bool Socket::Sender(char* msg){
    // Send a string with the length (int) of it ahead
    int len = strlen(msg);
    int hLen = htonl(len); // put it in network byte order
    if (send(sockfd, (char *) &hLen, sizeof(int), 0) == sizeof(int) &&
        send(sockfd, msg, len, 0) == len) 
    {
        return true;
    }
    Close();
    return false;
}

int Socket::Receive(char* msg, int maxlen){
    int recvResult;
    int len;
    int offset;

    // receive a string with the length (int) of it first
    if (recv(sockfd, (char *) &len, sizeof(int), 0) == sizeof(int))
    {
        len=ntohl(len); // put in host byte order
        // Check there is enough space
        if (len > maxlen)
        {
            // the receive chars is bigger than maxlen, 
            // either receive as many as maxlen or return error
            len=maxlen;
            // Close();
            // return -1;
        }
        offset=0;
        // loop until len chars are received, no more no less
        while (offset < len) 
        {
            recvResult = recv(sockfd, (char *) &msg[offset], len-offset, 0);
            if (recvResult <= 0)
            {
                Close();
                return -1;
            }
            offset +=recvResult;
        }
        // Succeeded, return len
        return len;
    }
    Close();
    return -1;
}
于 2014-05-17T12:26:13.213 回答