UDP非阻塞写入失败

时间:2013-11-25 14:52:00

标签: c sockets network-programming udp nonblocking

我曾在非阻塞TCP中工作,因为在非阻塞情况下,读取和写入都会失败。如果没有可用数据,TCP非阻塞读取可能会失败,如果对等端的TCP缓冲区已满,TCP写入可能会失败(我希望TCP缓冲区大小为64K)。

同样,如果没有可用数据,UDP读取(recvfrom)可能会失败。但UDP写入的失败案例是什么(sendto)。我认为在UDP写入中不会出现任何非块错误。因为TCP写入发送数据并等待来自另一方的ACK。但这不是UDP写入的情况,它只会发送并且出来并且它不会等待来自对等方的任何ACK。如果它不发送到另一方意味着它的丢包。

我对UDP非阻塞写入的理解是否正确?请解释一下?

2 个答案:

答案 0 :(得分:9)

UDP非阻塞发送失败的最可能原因是UDP套接字的内核出局数据缓冲区已满。在这种情况下,send()/ sendto()将返回-1,而errno将设置为EWOULDBLOCK。

请注意,非阻塞send()/ sendto()实际上并不会在返回之前将数据发送出网络设备;而是将数据复制到内核缓冲区并立即返回,此后内核有责任尽快将数据传输到网络。如果程序试图一次发送大量数据,则传出数据缓冲区可能会变满,因为CPU可以将新数据添加到缓冲区的速度比网络硬件可以将缓冲区的数据转发到网络的速度快得多。

如果你得到-1 / EWOULDBLOCK错误,通常最优雅的方法就是停止尝试发送该套接字,直到套接字select()的(或者poll()或者等等)为止准备换写。当发生这种情况时,您知道内核缓冲区已至少部分耗尽,您可以再次尝试send()/ sendto()调用。

如果您尝试发送的IP地址无效,则send()的另一个(不太可能)错误原因是。在任何情况下,你都应该检查errno并找出errno值是什么,因为这样可以让你更好地了解出错的地方。

顺便说一下,上述行为也不是UDP独有的;如果你尝试在套接字上发送()数据的速度比本地网卡可以耗尽套接字的话,你可以并且将会遇到与非阻塞TCP套接字相同的问题(即使远程对等端的接收窗口未满)内核缓冲区。

答案 1 :(得分:1)

  

因为TCP写入发送数据并等待来自另一方的ACK。

不,不。它将您的数据复制到套接字发送缓冲区,如果已满,则阻止或返回-1/EWOULDBLOCK/EAGAIN.

  

但这不是UDP写入的情况,它只会发送并且出来并且它不会等待来自对等方的任何ACK。

不,不。它将您的数据复制到套接字发送缓冲区,如果已满,则阻止或返回-1/EWOULDBLOCK/EAGAIN.

在这两种情况下,实际将字节放入线路与程序是不同步的。