服务器端的C ++ TCP套接字多个write()在客户端被视为单个读取

时间:2015-11-27 17:40:54

标签: c++ sockets tcp

我正在开发一个TCP连接程序,它由服务器和多个客户端组成。

服务器端

write(sockFd,message,strlen(message));
write(sockFd,message2,strlen(message2));

客户端

char msg[256];

bzero(msg, 256);
n = read (listenFd, msg, 255);
cout << "Msg1 " << msg << endl;

bzero(msg, 256);
n = read (listenFd, msg, 255);
cout << "Msg2 " << msg << endl;

问题是在服务器write()两个消息之后,客户端上的第一个read()可能会读取来自服务器的所有消息。 例如,输出是Msg 1 msg1content-of-msg2的内容。为什么会这样?

2 个答案:

答案 0 :(得分:1)

TCP是一种流媒体协议,因此数据以流形式出现,这意味着每次读取都会读取缓冲区中的数据(或者您请求的数据)。

因此,如果您想将数据分解为数据包或数据报,则需要使用自己的基于会话的协议。这样做的一种方法是为传出数据添加4个字节的长度。通过这种方式,读者可以首先读取长度,并知道数据报的其余部分有多大。

答案 1 :(得分:1)

这是因为套接字写入和读取的流特性。您必须实现自己的消息区分技术。

有些变体是:

  • Worser:实现自己的消息结束符号。
  • 更好:在消息发送该消息的大小之前(以字节为单位)。首先读取大小,然后读取大小给出的字节数。

使用C ++ 11,今天是2015年,不要做旧的C风格。

例如(为简单起见,省略了错误检查):

服务器端:

// choose this type once and never change it after first release!
using message_size_t = uint64_t;

void write_message(int sockfd, const std::string & message)
{
    message_size_t message_size{ static_cast<message_size_t>(message.size()) };

    // check error here:
    write(sockfd, &message_size, sizeof(message_size));

    // and here:
    write(sockfd, message.data(), message_size);
}

// use:
write_message(sockFd, message);
write_message(sockFd, message2);

客户方:

void read_bytes_internal(int sockfd, void * where, size_t size)
{
    auto remaining = size;

    while (remaining > 0) {
        // check error here
        auto just_read = recv(sockfd, where, remaining);
        remaining -= just_read;
    }
} 

std::string read_message(int sockfd)
{
    message_size_t message_size{ 0 };
    read_bytes_internal(sockfd, &message_size, sizeof(message_size));

    std::string result{ message_size, 0 };
    read_bytes_internal(sockfd, &result[0], message_size);

    return result;
}


// use:
cout << "Msg1 " << read_message(listenFd) << endl;
cout << "Msg2 " << read_message(listenFd) << endl;

(代码可能包含一些小错误,我在stackoverflow应答窗口中写了它,并且没有在IDE中进行语法检查。)