Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;服务器端的TCP套接字多写()在客户端被视为单读_C++_Sockets_Tcp - Fatal编程技术网

C++ C++;服务器端的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,

我正在开发一个带有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;
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()
调用中拆分。