2010-03-09 33 views
3

我已经阅读过各种网站和教程,但我仍然困惑。如果消息大于IP MTU,则send()返回发送的字节。剩下的信息会发生什么?我是否再次打电话send()并尝试发送其余消息?或者是IP层应该自动处理?TCP/UDP和以太网MTU碎片

回答

6

如果您使用的是TCP,那么呈现给您的接口就是一串字节。您不必担心字节流如何从连接的一端传输到另一端。你可以忽略IP层的MTU。实际上你可以完全忽略IP层。

当您拨打send()时,您计算机上的TCP协议栈将处理您推送到您的发送呼叫中的字节流所需的所有详细信息,以便在连接另一端的recv()调用中出现。

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

由于评论者要求它;)

在大多数TCP协议栈send()是最有可能失败,因为TCP堆栈的缓冲区已满,送一切(可能)的TCP窗口也充满了和流量控制是这意味着堆栈无法发送任何数据,直到远端确认某些数据,并且它不准备为您代替缓冲。我还没有碰到过一个TCP堆栈,将拒绝send()仅由于MTU的考虑,但我猜有些瘦了嵌入式系统的行为可能这样......

无论如何,如果send()回报比的字节数小于你提供了它,那么你应该在某个时候重新发送剩余的数据。经常send()会阻塞并等待,直到它可以发送所有数据,并且如果你已经将套接字设置为非阻塞模式,那么如果发送失败,你可能不想立即重试发送,因为你可能会结束在一个紧密的循环...

它可能会对你更具体的操作系统,你正在使用。

+5

+1,但是为了完成,您还应该处理这个问题最感兴趣的内容:如果'send'返回的值小于请求发送的字节(一个非常不可能的情况,因为堆栈将尝试处理它),如果必须的话,您有责任在稍后时间尝试发送其余数据。 – 2010-03-09 08:09:59

+0

真的不太可能吗?因为我看起来'send()'返回的值小于所请求的字节数,当请求的字节超过MTU时,所有的时间都发送出去。 – 2010-03-09 08:26:28

+0

Unix中的c。但你已经详细回答了我的问题。非常感谢!! – 2010-03-09 09:33:51

0

如果数据包太大而无法传输网络,则会发送ICMP碎片提示信号通知发件人以减小数据包大小并再次尝试。

如果您使用TCP,这些都是您应该期待网络层为您照顾的所有细节。现代IP堆栈实际上在幕后进行计算,以找出路径上最低的MTU,似乎已成为某种黑色艺术。

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

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

在Windows平台上使用阻塞套接字send()将在所有内容发送完成后立即返回。在其他平台上.. Linux等您需要不断发送更多的数据来推送数据。