我已经阅读了许多网站和在线教程,但仍然感到困惑。如果消息大于IP MTU,则send()
返回发送的字节数。剩下的消息会发生什么?我需要再次调用send()
并尝试发送剩余的消息吗?还是这是IP层应该自动处理的事情?
我已经阅读了许多网站和在线教程,但仍然感到困惑。如果消息大于IP MTU,则send()
返回发送的字节数。剩下的消息会发生什么?我需要再次调用send()
并尝试发送剩余的消息吗?还是这是IP层应该自动处理的事情?
send()
时,您计算机上的TCP堆栈将处理所有必要的细节,使您通过发送调用推入的字节流从连接的另一端的recv()
调用中出现。send()
可能会导致数据在多个recv()
调用中到达,并且多个send()
调用可能会导致数据在单个recv()
调用中到达。您对此无法控制。您正在处理一系列字节,每次调用recv()
都可以返回任何数量的字节,范围从1到当前未完成的数量(允许向recv()
调用传递足够的缓冲区)。send()
最有可能无法发送所有内容,因为TCP堆栈的缓冲区已满,并且(可能)TCP窗口也已满,并且流控制正在运行,这意味着堆栈不能发送更多的数据,直到远程端ACK一些数据并且它不准备代表您缓冲更多数据。我从未遇到过由于MTU考虑而拒绝send()
的TCP堆栈,但我想一些精简的嵌入式系统可能会有这种行为...send()
返回的字节数少于您提供的字节数,则应在某个时间重新发送剩余的数据。通常,send()
将阻塞并等待直到可以发送所有数据,并且如果您已将套接字设置为非阻塞模式,则可能不希望在发送失败时立即重试发送,因为您可能会陷入紧密的循环...如果数据包太大无法通过网络传输,则会发送ICMP分段提示,通知发送方减小数据包大小并重试。
如果使用TCP,这些都是你应该期望网络层为你处理的细节。现代IP堆栈实际上在幕后执行的操作,以确定路径上最低MTU似乎已经成为某种黑科技。
关于UDP,您仍然可以期望堆栈为您分段,但实际上,鉴于UDP的用例,这并不理想...根据您的应用程序,通过明确了解路径MTU,您可能会看到更好的性能。
关于send()问题,一些堆栈的行为不同,但WRT您的代码处理应该是相同的。假设您要发送100个字节... send()返回10个字节已发送。您需要继续使用剩余的90个字节调用send(),直到将整个消息推送到线路上为止。
在Windows平台上使用阻塞套接字,send()通常会在所有内容发送完毕后返回。在其他平台上,如Linux等,您需要更频繁地发送以推送数据。
send
返回的值小于要发送的字节数(这是非常不可能发生的情况,因为堆栈会尝试处理它),则如果必须的话,您有责任稍后再尝试发送剩余的数据。 - David Rodríguez - dribeassend()
收到比请求发送的字节数更小的返回值。 - Fantastic Fourier