2016-10-12 112 views
0

相对简单的问题:在使用Linux非阻塞套接字进行recv()时,是否有一种方法可以先验地确定可以接收多少数据?Linux非阻塞套接字:阻塞之前可以读取多少数据?

看来我总是会做一个额外的recv()调用来确定我已经排空了所有数据。

+2

如果你能得到这些信息,在你采取行动之前它已经陈旧了...... –

+1

你是什么意思'阻塞'之前?这是一个非阻塞的套接字。它不会阻止。你可以直接调用'recv()'直到发生EAGAIN/EWOULDBLOCK。不清楚你在问什么。 – EJP

回答

2

您可以使用ioctl()FIONREAD来获取套接字缓冲区中未读字节的数量。

但是,这也可能是双重系统调用,并且在您拨打recv()之前,仍然无法保证有更多数据未到达。

但有一种更简单的方法 - 您可以拨打recv(),它会返回实际读取的字节数。如果实际读取的字节数与请求的缓冲区大小相同,则只需重复调用。即使您不重复该呼叫,也会返回下一个select()调用,以确定是否还有更多可供读取的数据。

+0

我很确定recv(像read)可以自由地给你尽可能多的字节,因为它返回小于你的缓冲区大小并不意味着它没有数据。 – rivenmyst137

+0

@ rivenmyst137:Posix可能不保证这一点,但我没有看到任何其他行为的实现。无论如何,所描述的'recv()'和'select()'的组合在任何情况下都可以工作。 –

0

您可以使用recv中的MSG_PEEK标志来确定要从套接字缓冲区读取的当前字节数。如果应用程序在可以处理数据之前等待确定的字节数,则它可以依赖于MSG_PEEK。数据不会从套接字缓冲区中删除。但是,如果您在没有MSG_PEEK的情况下阅读,则ret将是相同的值。

ret = recv(sd, buf, MAX_CALL_DATA_SIZE, MSG_PEEK);

这种方法会导致额外的系统调用,直到的字节数的应用需求是套接字缓冲区。另外,在实际将数据读入应用程序时,并不保证会有更多的字节到达。