【发布时间】:2014-01-31 08:58:14
【问题描述】:
我有一个实时系统,所以我使用非阻塞套接字来发送我的数据 但是碰巧socket缓冲区满了, 所以发送函数的返回值小于我的数据长度。
如果我保存返回长度重新发送,和阻塞socket没有区别吗?
那么我可以获得套接字缓冲区的剩余大小吗?我可以先检查一下 如果足够了,那么我调用发送,跳过发送。
谢谢大家。
【问题讨论】:
-
操作系统:ubuntu 13.04 64bits
我有一个实时系统,所以我使用非阻塞套接字来发送我的数据 但是碰巧socket缓冲区满了, 所以发送函数的返回值小于我的数据长度。
如果我保存返回长度重新发送,和阻塞socket没有区别吗?
那么我可以获得套接字缓冲区的剩余大小吗?我可以先检查一下 如果足够了,那么我调用发送,跳过发送。
谢谢大家。
【问题讨论】:
好吧,阻塞和非阻塞之间是有区别的——如果你遇到短写,你就不会阻塞。这就是非阻塞的全部意义所在。它让您有机会在等待一些缓冲空间释放的同时做一些更紧迫的事情。
您关心的似乎是重复尝试编写完整消息,即一种投票形式。但是检查缓冲区中的空闲字节是同样的事情,你只是用 write 调用替换可用性调用。你真的没有从效率方面获得任何好处。
对此的常见解决方案是使用select 或poll 之类的东西来监视套接字描述符的写入(以及至少一些)字节的能力。这允许您停止轮询并将一些工作强加到内核上,以监控您的空间可用性。
也就是说,如果您真的想查看有多少可用空间,通常会有一些针对特定平台的变通方法,主要是带有各种平台特定参数的 ioctl 调用,例如 FIONWRITE、SIOCOUTQ、等等。您需要准确调查您的平台提供的内容。但是,同样,最好首先考虑一下这是否真的是您需要的东西。
【讨论】:
man (7) tcp 并搜索SIOCOUTQ。它是ioctl 的参数。你不会在 C 标准库中找到它,因为它依赖于平台,根据定义它是非标准的。
如果异步send 失败并显示EWOULDBLOCK/EAGAIN,则不会发送任何数据。然后,您可以尝试发送其他内容,或等到缓冲区再次空闲。
另见https://stackoverflow.com/questions/19391208/when-a-non-blocking-send-only-transfers-partial-data-can-we-assume-it-would-r - 那里讨论了一个相关问题。
【讨论】: