36

I have a server that receives a continuous stream of data. As opposed to reading multiple times from a socket, I would like to read the entire data in socket receive buffer with one system call to read().

Of course I can pass a large buffer and read() will try to fill it with all available data. But this would waste a lot of memory as most of the times the malloc'ed buffer would be bigger than actual data available on socket. Is there a way to query the available data on a socket?

4

6 回答 6

63

是的:

#include <sys/ioctl.h>

...

int count;
ioctl(fd, FIONREAD, &count);
于 2012-12-27T21:55:01.330 回答
5

No, there is not. Even if there were a way to do this, any answer you get would be immediately out of date (because new data may arrive at any time).

Note that when you pass a buffer to read(), the function will return when there is any amount of data to read (at least one byte), instead of waiting for the buffer to completely fill.

于 2012-12-27T00:06:38.897 回答
3

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

于 2012-12-27T01:34:08.803 回答
2

这是一个“有点”的答案:recv(char* buffer, size_t nytes, int flags)其中 flags 与:

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

于 2012-12-27T02:08:22.513 回答
1

您必须尝试发送和接收命令,并且能够逐个字符地在套接字中读取和写入,这样就不会浪费内存,甚至可以更好地进行通信。

于 2012-12-27T16:11:34.943 回答
0

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

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

于 2012-12-27T09:44:06.377 回答