TCP分段

3

我知道TCP提供类似流的数据传输,但主要问题是 - 在通过TCP发送数据时可能会发生什么情况?
1. 消息可以分成N个块以适应MTU大小。
2. 两条消息可以在1个recv调用中读取。

可能出现下一个情况吗?
例如MTU为1500字节。
客户端使用1498字节数据调用send。
客户端使用100字节数据调用send。
服务器调用recv并接收1500字节数据。
服务器调用recv并接收98字节数据。

因此,最终会出现这样一种情况,即第二个客户端发送的2个字节将在第一个服务器recv中接收到。

我的协议定义如下:
4个字节 - 数据长度
数据内容。

我想知道是否可能出现4个字节(数据长度)被拆分为2个块的情况?


即使它进行了分割,也没有任何影响。毕竟,您的数据将通过TCP正确地中继到目的地。http://en.wikipedia.org/wiki/Transmission_Control_Protocol - DumbCoder
就TCP而言,"消息"这种东西根本不存在。如果你的代码中有关于消息的概念,TCP对此一无所知。 - David Schwartz
2个回答

8

是的,字节流可以在任意字节边界上拆分。您肯定可以以8种不同的方式拆分4个字节的数据长度标头:

4
1-3
2-2
3-1
1-1-2
1-2-1
2-1-1
1-1-1-1

其中一些情况比其他情况更容易发生,但您必须考虑到它们。可以处理此代码可能如下所示:

unsigned char buf[4];
size_t len = 0;
while (len < sizeof(buf)) {
    ssize_t n = recv(s, buf+len, sizeof(buf)-len, 0);
    if (n < 0) {
        // error handling here
    }
    len += n;
}
length = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);

2
重要的是,如果您在继续之前阻塞并等待完整的四个字节,则这并不重要。TCP会尽其所能透明地重新组装分段数据。 - cdhowie
@cdhowie - 虽然这可能是真的,但并不能保证所有软件在代码和线之间构造数据包时都会按照每个SendData调用的1对1方式进行。也就是说,如果在某个地方,传递到该调用中的字节数组被认为对于情况来说太大,那么没有任何保证消息不会被分成多个数据包。 - Spencer Ruport

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接