sockets - POSIX POLLOUT和阻止文件描述符

标签 sockets pipe posix polling

根据the POSIX poll docsPOLLOUT标志指示“可以写入正常数据而不会阻塞”。但是有多少数据?有没有固定的保证,或者有什么办法可以找出有多少缓冲空间?

我正在写管道和 socket 。通常,我的程序不会得到EINTR,因为所有期望的信号都是通过signalfd/kqueue处理的;据我所知,这意味着我可以期望write始终会阻塞,直到所有请求的数据都已传输。

我不确定我想要这个。理想情况下,我只想写入尽可能多的数据,以便缓冲区中有足够的空间,以便代码可以尽快返回轮询循环而不会阻塞。 (如果还有数据要写,我的代码可以再次检查同一FD上的POLLOUT,并在有可用空间时再次执行相同的操作。)

有什么办法可以使这项工作顺利进行吗? poll似乎很适合从阻塞管道/套接字FD读取:设置POLLIN标志时,您读入缓冲区,并且在不阻塞的情况下获得了尽可能多的可用空间。但是开始编写时看起来有点不方便!我想念什么吗?

还是所有这些只是想告诉我使用O_NONBLOCK

我正在使用OS X和Linux。

最佳答案

从表面上看,您可以保证最多可以写入1个字节。

切换到非阻塞模式也无济于事。当然,您不会阻塞,但随后必须弄清楚如何处理非阻塞写入未写入的任何数据。无论文件描述符的阻止模式如何,poll()都会为您提供相同的结果。

您可以尝试一些替代方法,例如异步IO或ZeroMQ之类的框架。

异​​步IO

asynchronous IO,它可以有效地归结为让大量的后台线程为您完成编写工作。很好,但是您必须管理数据生存期/所有权问题。您必须将所有正在编写和未修改的内容保留在原处,直到被告知异步写入已完成。至少可以这样说。

框架

另一种选择是消息框架,例如ZeroMQ。还有其他-nanomsg(由执行ZeroMQ的同一人编写),DDS,Corba(如果您敢)和ESA的TASTE等。

直接更换

这些都有不同的质量,但是ZeroMQ和nanomsg特别设计为将代码从使用标准套接字和管道API转换为使用它们自己的代码(特别是nanomsg)的痛苦最小的方法。

消息而不是流

所有这些都是面向消息的,而不是面向流的,它们都很好地管理了通过某种连接为您传递数据这一痛苦的事情,并且还解决了数据生命周期问题。

基础运输

ZeroMQ和nanomsg将跨管道,套接字,共享内存等工作。它们还可以将普通文件描述符并入等效的poll()中,以在代码等待输入时使用(如果您有一个fd串行端口也可以收听)。

与异步IO的比较

此类框架与异步io之间的区别如下。对于框架,连接另一端的软件也必须使用相同的框架,否则它们将无法通信。使用aio,另一端仍然可以使用普通的同步套接字函数调用,因为从根本上说,它们的全部仍只是一个流连接。

框架比aio更不透明。谁知道框架内正在进行多少数据复制?通常这并不重要,前提是您的RAM比网络快得多。

0MQ/nanomsg与其余

ZeroMQ/nanomsg与DDS/Corba/TASTE之类的东西之间的区别在于,后者还包含序列化。它们允许您使用与平台无关的描述语言来指定消息结构,该语言可以“编译”为您使用的任何源代码语言(C,C#,JAVA等)。这很自然,有点像声明C结构。这样一来,您可以在连接的另一端拥有完全不同的平台和编程语言,并且它们仍然可以通话。 DDS和Corba为此使用IDL,TASTE使用ASN.1(在所有可能的方式上都比较出色),但是TASTE很难使用。

通过使用Google Protocol Buffer 或ASN.1(或任何many available)对数据进行序列化,并使用ZeroMQ/nanomsg将由序列化程序生成的字节流作为消息进行传输,可以使用ZeroMQ/nanomsg达到相同的效果。

关于sockets - POSIX POLLOUT和阻止文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35215224/

相关文章:

c++ - send() 函数返回所需的更多字节 C++

mysql - 找不到 mysql.sock

sockets - nginx 如何复用单个套接字

c++ - 如何将管道作为文件传递给 C 应用程序?

c - GNU C 使用管道的多进程处理

条件变量 - 意外行为

c - exec* POSIX 函数中的管道

node.js - 如何使用 Node.js net.Socket 像使用终端一样与 Postgresql 数据库通信

python - 使用 Python 强制另一个程序的标准输出不被缓冲

c - 在 C 中使用管道传递多个数据 block