包含消息长度的两个字节标头上的部分recv()呢?

What about partial recv() on two byte header containing message length?

本文关键字:recv 两个 消息 包含 字节      更新时间:2023-10-16

我一直在阅读一些插座指南,例如Beej的网络编程指南。现在很明显,在单个recv()呼叫中收到多少个字节可以保证。因此,例如前两个字节说明消息长度应发送,然后发送消息。因此,接收器接收前两个字节,然后在循环中接收到整个消息。一切都很好,花花公子!?

我被一位同事询问我的消息。例如。如果某种程度上,我在一次recv()呼叫中收到两个字节,这些字节实际上位于消息本身的中间,并且它将看起来像某种值的整数?这是否意味着发送的其余数据将不同步?那部分接收标头,即一次字节呢?

也许这是过度思考的,但是我在任何地方都找不到这一点,我只想确定,如果这可能是对通信完整性的威胁,我会处理这一点。

谢谢。

它不会过度思考。TCP呈现流,因此您应该以这种方式对待。有关TCP的许多问题是由于网络问题引起的,并且可能不会在开发过程中发生。

用(4个字节)魔术启动一条消息,您可以在预期顺序(通常是大的endian)中查找(4个字节)长度。接收时,当时读取标题的每个字节,因此您可以将其处理。基于此,您可以在持久的TCP连接中接受消息。

请注意,每条消息启动新连接时,您就会知道起点。但是,如果只是要滤除一些无效的消息,也不会伤害发送魔术。

不需要校验和,因为TCP显示了一个可靠的字节,该字节已由TCP的接收部分检查,并且仅在发送/接收的编码问题时才需要同步。

另一方面,UDP发送数据包,因此您知道会发生什么,但是不能保证交货和订单。

您的同事错误。TCP数据无法订购。但是,您应该将MSG_WAITALL标志调查到recv(),以克服两个长度字节分别到达的可能性,并在接收消息主体时消除循环的需求。

您有责任使您的客户端和服务器共同同步,在TCP中没有订单交付,如果您通过调用recv()获得某些东西,您可以认为有东西'您没有收到的任何东西。

所以问题是如何同步发送者和接收器?正如Stefaanv所说,它很容易,发件人和接收者知道他们的起点。因此,您可以为网络通信定义协议。例如,可以这样定义协议:

4个字节,包括消息类型和有效载荷长度

消息的其余部分是有效载荷长度

这样,您必须在发送实际有效载荷之前发送4个字节标头,然后发送实际有效载荷。

由于TCP已使用订单可靠交付,因此您可以为每个包进行两个recv()调用。一个recv()调用,长度为4个字节,用于获取下一个有效载荷大小,另一个调用reacv()在标题中指定的大小。这是使recv()阻止以始终进行同步所必需的。

一个例子就是这样:

#define MAX_BUF_SIZE       1024 // something you know
char  buf[MAX_BUF_SIZE];
int recvLen = recv(fd, buff, 4, MSG_PEEK);
if(recvLen==4){
    recvLen = recv(fd, buff, 4);
    if(recvLen != 4){
          // fatal error
    }
    int payloadLen = extractPayloadLenFromHeader(buf);
    recvLen = recv(fd, buff, payloadLen, MSG_PEEK);
    if(recvLen == payloadLen){
        recvLen = recv(fd, buff, payloadLen); // actual recv
        if(recvLen != payloadLen){
             // fatal error
        }
        // do something with received payload
     }
}

您可以看到,我首先将带有msg_peek标志的RECV调用,以确保实际上是否有4个字节,然后收到了实际标题。有效载荷

相同