TCP / UDP和以太网MTU碎片

时间:2010-03-09 07:57:15

标签: c tcp send fragmentation mtu

我在线阅读了各种网站和教程,但我仍感到困惑。如果消息大于IP MTU,则send()返回发送的字节。消息的其余部分会发生什么?我是否再次致电send()并尝试发送其余信息?或者IP层应该自动处理什么?

2 个答案:

答案 0 :(得分:6)

如果您使用的是TCP,那么呈现给您的界面就是字节流。您无需担心字节流如何从连接的一端传递到另一端。您可以忽略IP层的MTU。实际上,您可以完全忽略IP层。

当您拨打send()时,您计算机上的TCP堆栈将处理您推送到发送呼叫的字节流所需的所有详细信息,以便从另一端的recv()个呼叫中显示连接。

要记住的一件事是,使用TCP,您正在处理流,这意味着一个send()可能会导致数据到达多个recv()个来电,多个send()来电可能导致数据在单个recv()调用中到达。你无法控制这一点。您正在处理字节流,每次调用recv()都可以从1返回任意数量的字节到当前未完成的数字(允许将足够的缓冲区传递给recv()调用)。

因为评论者要求它;)

在大多数TCP堆栈上send()最有可能无法发送所有内容,因为TCP堆栈的缓冲区已满并且(可能)TCP窗口也已满并且流控制正在运行,这意味着堆栈可以' t发送更多数据,直到远程端确认某些数据,并且它不准备代表您进行缓冲。我没有遇到过仅因MTU考虑因素而拒绝send()的TCP堆栈,但我猜一些精简的嵌入式系统可能会表现得那么......

无论如何,如果send()返回的内容少于您提供的字节数,那么您应该在某个时刻重新发送剩余的数据。通常send()将阻塞并等待它可以发送所有数据,如果您已将套接字设置为非阻塞模式,那么您可能不希望立即重试发送,如果它无法发送所有内容可能最终会陷入困境......

您可能更有兴趣了解您正在使用的操作系统。

答案 1 :(得分:0)

如果数据包太大而无法通过网络,则会发送ICMP碎片提示,通知发送方减小数据包大小并重试。

如果您使用TCP,那么您应该期望网络层为​​您提供所有细节。现实的IP堆栈实际上在幕后找出路径中最低的MTU似乎已经成为一种黑色艺术。

WRT UDP您仍然可以期待堆栈为您分段,但实际上UDP的用例并不理想..根据您的应用程序,您可能会通过明确了解路径MTU来看到更好的性能。

...在send()问题上,一些堆栈的行为有所不同,但处理WRT你的代码应该是相同的。假设您有100个字节要发送... send()返回发送的10个字节。你需要继续使用剩余的90个字节来调用send,直到它全部推出线路以发送整个消息。

在Windows平台上使用阻塞套接字send()通常会在发送完所有内容后返回..在其他平台上...... Linux等你需要不断发送以推送数据。