C++ C++;服务器端的TCP套接字多写()在客户端被视为单读
我正在开发一个带有TCP连接的程序,它由一个服务器和多个客户端组成 服务器端C++ C++;服务器端的TCP套接字多写()在客户端被视为单读,c++,sockets,tcp,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,
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;
charmsg[256];
bzero(msg,256);
n=读取(listenFd,msg,255);
coutTCP是一种流协议,因此数据以流的形式出现,这意味着每次读取将读取缓冲区中的数据量(或您请求的数据量)
因此,如果您想将数据分解为数据包或数据报,则需要使用您自己的基于会话的协议。一种方法是在传出数据前加上4个字节的长度。这样,读者可以首先读取长度,这样就知道数据报的其余部分有多大。这是因为套接字写入和读取的流性质。您必须实现自己的消息识别技术
有些变体是:
- 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);
//选择此类型一次,在第一次发布后不要更改它!
使用消息\u size\u t=uint64\u t;
无效写入消息(int sockfd、const std::string和message)
{
message_size_t message_size{static_cast(message.size())};
//在此处检查错误:
写入(sockfd,&message_size,sizeof(message_size));
//在这里:
写入(sockfd,message.data(),消息大小);
}
//使用:
写消息(sockFd,消息);
编写_消息(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;
void read\u bytes\u internal(int sockfd,void*where,size\u t size)
{
自动剩余=大小;
而(剩余>0){
//在这里检查错误
auto just_read=recv(sockfd,其中,剩余);
剩余-=刚刚阅读;
}
}
std::字符串读取消息(int sockfd)
{
消息大小\u t消息大小{0};
读取字节内部(sockfd和消息大小、消息大小);
字符串结果{message_size,0};
读取字节内部(sockfd和结果[0],消息大小);
返回结果;
}
//使用:
cout TCP是一种流协议——没有消息边界。有没有办法让客户端以不同的读取方法读取这两条消息?@ZZZ no.接收它,然后手动拆分消息。顺便说一句,您可能不知道发送/接收可能无法完全处理给定的长度。检查返回值并使用循环。Yes和no--“Yes”,因为您可以按照@deviantfan所说的操作,自己解析/拆分消息。“否”,因为没有内置机制可以为您执行此操作。“基于会话的”协议?“这样,读者可以首先读取长度,这样就知道数据报的其余部分有多大。”--要小心,因为即使是4字节的“长度”字段也可能会在多个recv()
调用中拆分。