C 如何缓冲非阻塞IO?

C 如何缓冲非阻塞IO?,c,io,nonblocking,buffered,C,Io,Nonblocking,Buffered,当我需要阻塞文件描述符上的缓冲IO时,我使用stdio。但若我根据手动stdio将文件描述符转换为非阻塞模式,则缓冲是不可用的。经过一些研究,我发现BIO可以用于缓冲非阻塞IO 但可能还有其他选择吗 我需要这样做是为了避免在多连接环境中使用线程。我看到这个问题现在已经编辑好了,至少比以前更容易理解 不管怎样,这不是矛盾吗 使I/O无阻塞是因为您希望能够快速读取少量数据,通常会牺牲吞吐量以换取延迟。 您之所以将其设置为缓冲,是因为您不太关心延迟,而是希望通过以延迟换取吞吐量来有效利用I/O子系统。

当我需要阻塞文件描述符上的缓冲IO时,我使用stdio。但若我根据手动stdio将文件描述符转换为非阻塞模式,则缓冲是不可用的。经过一些研究,我发现BIO可以用于缓冲非阻塞IO

但可能还有其他选择吗


我需要这样做是为了避免在多连接环境中使用线程。

我看到这个问题现在已经编辑好了,至少比以前更容易理解

不管怎样,这不是矛盾吗

使I/O无阻塞是因为您希望能够快速读取少量数据,通常会牺牲吞吐量以换取延迟。 您之所以将其设置为缓冲,是因为您不太关心延迟,而是希望通过以延迟换取吞吐量来有效利用I/O子系统。 同时做这两件事似乎是矛盾的,很难想象

你想要什么语义学?如果您这样做:

int     fd;
char    buf[1024];
ssize_t got;

fd = setup_non_blocking_io(...);
got = read(fd, buf, sizeof buf);
如果有3个字节可用,您希望有什么行为?阻塞/缓冲I/O可能会阻塞,直到能够读取更多数据以满足您的请求,非阻塞I/O将立即返回3个可用字节


当然,如果你有一些协议在上面,它定义了某种消息结构,这样你就可以知道这个I/O是不完整的,在我有更多数据之前我不能解析它,你可以自己在那个级别缓冲它,在收到完整的消息之前不向上传递数据。

我想你说的是。这是在没有线程的情况下处理大量网络连接的标准方法,在多人游戏服务器引擎中非常常见。python中的另一个实现是

基本算法是:

每个套接字都有一个缓冲区 检查哪些套接字已准备好读取、选择、轮询或只是迭代 对于每个插座: 调用recv并将内容累积到套接字的缓冲区中,直到recv返回0或ewoldblock出现错误 使用缓冲区的内容调用套接字的应用程序级数据处理程序 清除套接字的缓冲区
您可以为每个打开的文件描述符创建一个带有缓冲区的结构,然后累积这些缓冲区,直到recv返回0或者您的缓冲区中有足够的数据可以处理

如果我正确理解了您的问题,您就不能使用缓冲区,因为如果是全局的,则使用多个连接将数据写入同一缓冲区;如果是本地的,则仅写入小块数据

在任何情况下,您的程序都必须能够通过文件描述符识别数据的来源,并相应地对其进行缓冲


线程也是一种选择,它不像许多人说的那么可怕。

根据协议,您当然可能需要为非阻塞网络节点客户端或服务器缓冲读取

通常,这些缓冲区提供多个索引偏移量,记录处理的最后一个字节的位置和读取的最后一个字节的位置,该位置与处理的偏移量相同或大于处理的偏移量。它们还应该提供更丰富的压缩缓冲区、透明缓冲区大小管理等语义

在Java中,至少非阻塞网络io NIO包还提供了一组数据结构ByteBuffer等,这些数据结构旨在提供通用数据结构

对于C,要么存在这样的数据结构,要么您必须使用自己的数据结构。一旦有了它,只需读取尽可能多的可用数据,并让缓冲区管理溢出等问题,例如跨消息帧边界读取字节,并使用标记偏移量标记已处理的字节

正如Android所指出的,您很可能需要为每个打开的连接创建匹配的缓冲区。

这正是您想要的


我在工作中使用它,效果很好。请注意,虽然它还没有,但很快就会有异步DNS解析。瑞安建议这样做。我正在尝试采用udns,而不是现在阻止getaddrinfo。

你能提供一些更详细的信息吗,比如你正在使用的函数等。我同意,这个问题很难回答。我甚至都不明白它现在的措辞。你看在BIO上的意思是在阻止IO上阅读吗?问题的背景是什么?为什么要避免线程?在一个服务于多个连接的程序中,有线程通常会使实现更干净、更易于维护。线程太糟糕了。首先它是不可维护的,其次它很慢。这样做可以避免在多连接应用程序中使用线程。这并不矛盾。非阻塞I/O最常用于程序需要执行其他工作(通常为其他描述符提供服务)且不希望阻塞任何给定描述符的情况。这和等待完全缓冲区有点不同。在反应器模式的描述中,我发现了libowfat。这条线最能满足我的需要。感谢Doesnt NIO代表本机输入O 输出,而不是非阻塞输入输出?