非阻塞send()/ write()和待处理数据处理

时间:2013-05-20 16:46:35

标签: linux sockets network-programming udp

当发送(或写入)缓冲区将满时,让我说,只有theres只有500字节的空间。如果我有一个NONBLOCKING fd,并且

  n = send(fd, buf, 1000,0)

这里我得到n< 0,我可以得到EWOULDBLOCK或EAGAIN错误。我的问题是:

1这里,send将500个字节写入发送缓冲区或0个字节写入发送缓冲区?

2如果500字节被发送到缓冲区并且fd是UDP套接字,那么数据报被分成两部分?

3我需要使用fd发送许多数据报,如果此时发送缓冲区已满(如果有EWOULDBLOCK或EAGAIN错误),我需要创建一个挂起的数据报列表(FIFO队列) )。每次我想发送一些数据报时,我都要检查待处理的列表,看它是否为空。如果它不为空,则首先在待处理列表中发送数据报。在我看来,这个设计有点麻烦。设计类似于扩展内核(BTW,它是在内核吗?)发送缓冲区的用户空间挂起列表。对此有更好的解决方案吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

以下仅适用于UDP(仅适用于Linux,但其他类似),但这似乎是您所要求的。

在UDP套接字上设置非阻塞模式完全不相关(用于发送),因为发送永远不会阻塞 - 它会立即发送数据包,而不进行任何缓冲。

有可能(如果机器非常繁忙)存在缓冲区空间问题(用于数据包处理的瞬态数据包缓冲区用完),但在这种情况下,无论fd是否阻塞,调用都将返回ENOBUFS或非阻塞。这应该是非常罕见的。

如果您生成数据包的速度比网络速度快(在快速机器和10Mbit以太网端口上相当容易),则存在潜在问题,在这种情况下,内核将开始丢弃传出数据包。不幸的是,没有简单的方法来检测何时发生这种情况(您可以检查TX丢弃数据包的接口,但这不会告诉您哪些数据包被丢弃)。

如果使用UDP_CORK套接字选项,它可能会出现问题,该选项会缓冲写入套接字的数据而不是发送数据包,并且仅在未设置CORK选项时发送单个数据包。在这种情况下,如果缓冲区变得太大,您将获得EMSGSIZE(同样,NONBLOCKING设置无关紧要)。

答案 1 :(得分:1)

如果您正在谈论UDP,那么您完全不在此处 - 对于UDP,SO_SNDBUF套接字选项的值会限制您可以发送的数据报的大小。换句话说,没有真正的每插槽发送缓冲区(尽管数据仍然在内核中排队以由适当的网络控制器发送出去)。如果你一次尝试EMSGSIZE,你会得到send(2)

对于TCP,当发送缓冲区中根本没有空间时,你只能获得EWOULDBLOCK,即没有数据从用户复制到内核。否则sent(2)的返回值会告诉您已经复制了多少字节。