我有一台接收连续数据流的服务器。与从套接字多次读取相反,我想通过对read()
的一次系统调用来读取套接字接收缓冲区中的整个数据。
当然我可以传递一个大缓冲区,read()
会尝试用所有可用数据填充它。但这会浪费大量内存,因为malloc的缓冲区大多数时候都比socket上的实际数据大。有没有办法查询套接字上的可用数据?
答案 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