我正在通过TCP / IP套接字读取数据流。流负载非常不均匀。有时大量的数据每秒都会到达,有时一小时内没有数据。在长时间不活动的情况下(没有来自远程服务器的数据,但连接仍在线),我的程序应该采取一些措施。
我正在使用select()实现超时。它告诉我是否有数据准备就绪,但我不知道究竟能读多少而不会导致read()阻塞。阻止是不可接受的,因为它可能比我需要的超时时间长得多。
为了提高效率,将流读入大缓冲区,并使用该缓冲区大小调用read()调用。
如果要填充的缓冲区大于套接字中现有的可用数据量,那么select()之后的read()会阻塞吗?
答案 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)