read()会在select()之后阻塞吗?

时间:2011-03-18 12:29:47

标签: linux sockets

我正在通过TCP / IP套接字读取数据流。流负载非常不均匀。有时大量的数据每秒都会到达,有时一小时内没有数据。在长时间不活动的情况下(没有来自远程服务器的数据,但连接仍在线),我的程序应该采取一些措施。

我正在使用select()实现超时。它告诉我是否有数据准备就绪,但我不知道究竟能读多少而不会导致read()阻塞。阻止是不可接受的,因为它可能比我需要的超时时间长得多。

为了提高效率,将流读入大缓冲区,并使用该缓冲区大小调用read()调用。

如果要填充的缓冲区大于套接字中现有的可用数据量,那么select()之后的read()会阻塞吗?

5 个答案:

答案 0 :(得分:16)

实际上它不应该阻塞(这就是select()的用途!),但实际上,可能,异常。通常,read()应该返回到你指定的最大字节数,这可能包括零字节(这实际上是一个有效的事情!),但它应该在之前报告准备就绪之后永远不会阻塞。

然而,请参阅Linux select手册页:

  

在Linux下,select()可能会报告   套接字文件描述符为“准备好了   阅读“,尽管如此   后续读取块。这可以   例如,数据发生时   到了,但经过检查有错   校验和并被丢弃。也许有   是其他情况下的文件   描述符被虚假报告为   准备。因此,使用起来可能更安全   套接字上的O_NONBLOCK不应该   块。

答案 1 :(得分:3)

可以O_NONBLOCK / fcntl设置F_SETFL,并且应该导致非阻塞read

答案 2 :(得分:2)

阻塞文件描述符将在read()上阻塞,直到有东西要读 - 可能是一个字节或整个请求。如果没有要读取的内容,非阻塞描述符将不会阻塞read()。 Select()不是read()。它基本上将进程置于休眠状态并监视文件描述符,包括非阻塞描述符。当其中一个描述符上有活动(或超时期限到期)时,选择返回并且您可以读取您的数据,或者在超时的情况下执行其他操作。

所以你有两个不同的问题。 (1)当没有数据时你想“采取一些行动”。这是选择超时。 (2)一旦有数据(由select通知),你不想阻止读取。这是非阻塞模式。当您在非阻塞读取上获得EAGAIN时,您将循环回到选择和/或“执行某些操作”并循环返回以进行选择。

答案 3 :(得分:0)

不,read()将读取指定的大小并返回读取的实际字节数,可以更少。

答案 4 :(得分:-1)

您可以使用默认情况下不阻止的recv()(如果未指定标志MSG_WAITALL)