如何在C中多路复用缓冲IO?

如何在C中多路复用缓冲IO?,c,select,C,Select,我正在使用C语言开发一个简单的聊天服务器。为了从我的所有客户端获取传入消息,我需要使用select系统调用。我决定使用stdio函数来简化操作,但我担心库的缓冲会影响select的使用(即数据将保持缓冲状态,从fd读取,但不可见)。在C中应该使用什么函数来多路复用缓冲I/O 当我写这篇文章时,我记得文件流可以被放入无缓冲模式。这行吗?不幸的是,无缓冲模式没有帮助。例如,fgets()。为此,它将多次调用底层的read(),即使在未缓冲时也是如此,并且在第一次调用之后的调用将不受您的控制。这同样适

我正在使用C语言开发一个简单的聊天服务器。为了从我的所有客户端获取传入消息,我需要使用
select
系统调用。我决定使用
stdio
函数来简化操作,但我担心库的缓冲会影响
select
的使用(即数据将保持缓冲状态,从fd读取,但不可见)。在C中应该使用什么函数来多路复用缓冲I/O


当我写这篇文章时,我记得文件流可以被放入无缓冲模式。这行吗?

不幸的是,无缓冲模式没有帮助。例如,
fgets()。为此,它将多次调用底层的
read()
,即使在未缓冲时也是如此,并且在第一次调用之后的调用将不受您的控制。这同样适用于
fscanf()
fprintf()
,甚至
fread()
fwrite()


如果您确实坚持使用stdio,您可以在多个线程中执行阻塞IO,但这不值得费心(以及潜在的系统过载)。使用多路IO的唯一明智的方法是使用低级读取操作读取数据,然后使用stdio工具(如
sscanf

)解析数据。您仍然有套接字描述符,不是吗?还是在你对它们做了
fdopen
之后就把它们扔掉?在这种情况下,您可以使用
fileno
将它们取回,并且仍然使用
select
进行多路复用。来自stdio的函数,如
scanf
read
可能会读取比当前可用的数据更多的数据并阻塞。他们在
select
@user4815162342上玩得不好是的,我只是误解了他的意思said@JoachimPileborg我还有描述词,但是我只是想,由于混合调用
write
fprintf
是一种不好的做法,所以混合调用
select
fgets
可能是一个不好的主意,尽管我认为应该注意的是
select
对文件描述符的值有一个上限:“fd_集是一个固定大小的缓冲区。执行FD_CLR()或FD_SET()时,如果FD的值为负值或等于或大于FD_setize,则会导致未定义的行为。”@JeremyRodi指出,但我认为使用太多不会有问题clients@JeremyRodi在这个问题的上下文中,什么适用于
select()
也适用于更好的替换,例如
poll()
epoll()
、kque等
select()
仅启用事件驱动编程和IO处理,而stdio与之根本不兼容。@user4815162342我理解;我只是想让询问者意识到这一限制,不管什么与stdio兼容。@JeremyRodi另一方面,还应该注意的是,一个人必须多路传输数百个数据文件描述符甚至接近
select()
FD_SETSIZE
在今天的Linux系统上是1024)的限制。因此,在实践中这不太可能成为问题,除非是高负载服务器的专业开发人员。