如何在C和Linux中检查套接字可用的数据量

时间:2012-12-27 00:02:54

标签: c linux sockets

我有一台接收连续数据流的服务器。与从套接字多次读取相反,我想通过对read()的一次系统调用来读取套接字接收缓冲区中的整个数据。

当然我可以传递一个大缓冲区,read()会尝试用所有可用数据填充它。但这会浪费大量内存,因为malloc的缓冲区大多数时候都比socket上的实际数据大。有没有办法查询套接字上的可用数据?

6 个答案:

答案 0 :(得分:52)

是:

#include <sys/ioctl.h>

...

int count;
ioctl(fd, FIONREAD, &count);

答案 1 :(得分:4)

不,没有。即使有办法做到这一点,你得到的任何答案都会立即过时(因为新数据可能随时到达)。

请注意,当您将缓冲区传递给read()时,该函数将在要读取的任何数据量(至少一个字节)时返回,而不是等待缓冲区完全填补。

答案 2 :(得分:2)

这是一种“某种”答案:recv(char* buffer, size_t nytes, int flags)其中标志与OR进行“或”运算:

MSG_PEEK
This flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data.

这样你就可以看到缓冲区中是否存在任意数量的字节,而不会不可逆地读取缓冲区。这是一个半答案,因为它不是最有效的方法,并且MSG_PEEK通常在消息具有已知长度标题时使用,如下所示:

000123DT001    

其中00123是包含标题的整个邮件的长度,DT是邮件的类型,001是发件人的重试次数。这个想法是你可以获取一些东西,告诉你有多少字节可以完整地读取一条消息。你对消息不感兴趣。但这就是MSG_PEEK

背后的原因

答案 3 :(得分:2)

你必须尝试发送和接收命令,以及你能够逐个字符地读取和写入,这样就不会浪费内存,甚至更好的沟通。

答案 4 :(得分:1)

您可以使用Non-bloking sockets,或选择()/ poll()。我更喜欢非阻塞套接字,因为我可以在等待新数据时做其他事情。

答案 5 :(得分:0)

我认为您正在尝试通过单个系统调用获取许多数据包,以减少系统调用造成的开销。

所以你可以尝试用于Linux 2.4或2.6+内核的PACKET套接字接口试试这个http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt