我正在通过TCP / IP套接字读取数据stream。 河stream负荷非常不平衡。 有时会有大量的数据每秒到达,有时一小时没有数据。 在长时间不活动的情况下(远程服务器没有数据,但连接仍在线),我的程序应该采取一些行动。
我使用select()实现了一个超时。 它告诉我是否有数据准备好,但是我不知道我能读多less,而不会导致read()被阻塞。 阻止是不可接受的,因为它可能会持续比我需要的时间更长的时间。
为了提高效率,将stream读入大缓冲区,并使用该缓冲区大小提供read()调用。
如果要填充的缓冲区大于当前在套接字中可用的数据量,select()将会读取()块吗?
其实它不应该阻塞(这是什么select()是!),但实际上,它可能 ,例外。 通常情况下,read()应该返回到您指定的最大字节数,可能包含零字节(这实际上是一个有效的事情发生!),但它应该永远不会阻止之前已经报告准备就绪。
不过,请参阅Linux 选择手册页:
在Linux下,select()可能会报告套接字文件描述符为“准备好读取”,而后续的读取块。 例如,这可能发生在数据已经到达但检查错误的校验和被丢弃的情况下。 在其他情况下,文件描述符被虚假地报告为就绪。 因此,在不应该阻塞的套接字上使用O_NONBLOCK可能会更安全。
有可以通过fcntl
/ F_SETFL
设置的O_NONBLOCK
,并且应该导致无阻塞的read
。
阻塞文件描述符将在read()上阻塞,直到有东西要读取 – 可能是一个字节或整个请求。 如果没有可读的内容,则非阻塞描述符将不会在read()上阻塞。 Select()不是read()。 它基本上使进程进入休眠状态并监视文件描述符,包括非阻塞描述符。 当其中一个描述符有活动时(或超时时间到期),选择返回,您可以读取数据,或在超时情况下执行其他操作。
所以你有两个单独的问题。 (1)在没有数据的时候想要“采取一些行动”。 这是选择超时。 (2)一旦你有数据(通过选择通知)你不想阻止阅读。 这是非阻塞模式。 当您在非阻塞读取中获得EAGAIN时,您将循环回到选择和/或“采取一些操作”并循环选择。
不, read()
将读取到指定的大小,并将返回读取的实际字节数,可能会少一些。
您可以使用默认情况下不阻塞的recv()(如果没有指定标志MSG_WAITALL)