3

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

4

2 回答 2

6

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

当您调用send()计算机上的 TCP 堆栈时,将处理您推送到发送调用中的字节流从recv()连接另一端的调用中出现所需的所有细节。

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

由于评论者要求它;)

在大多数 TCP 堆栈send()上最有可能无法发送所有内容,因为 TCP 堆栈的缓冲区已满,并且(可能)TCP 窗口也已满并且流控制正在运行,这意味着堆栈无法发送更多数据,直到远程end ACKs 一些数据,它不准备代表您再缓冲。我还没有遇到一个 TCP 堆栈,它会send()因为 MTU 的考虑而拒绝,但我猜一些精简的嵌入式系统可能会以这种方式运行......

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

更具体地了解您正在使用的操作系统可能对您有用。

于 2010-03-09T08:03:16.750 回答
0

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

如果您使用 TCP,这些都是您应该期望网络层为​​您处理的所有细节。现代 IP 堆栈实际上在幕后所做的以找出沿途最低的 MTU 似乎已成为某种黑色艺术。

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

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

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

于 2010-03-09T08:18:53.173 回答