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

时间:2022-08-06 16:58:35

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().

我有一个接收连续数据流的服务器。与从套接字中多次读取不同,我希望使用一个系统调用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?

当然,我可以传递一个大的缓冲区,read()将尝试用所有可用的数据填充它。但是这将浪费大量的内存,因为大多数情况下,malloc'ed缓冲区会大于套接字上的实际数据。有办法查询套接字上的可用数据吗?

6 个解决方案

#1


48  

Yes:

是的:

#include <sys/ioctl.h>

...

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

#2


3  

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.

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

#3


2  

This is a "sort of" answer: recv(char* buffer, size_t nytes, int flags) where flags is OR'ed with:

这是一种“类型”的回答:recv(char* buffer, size_t nytes, int 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.

Such that you can see if an arbitrary number of bytes exists in the buffer, without irreversibly reading the buffer. This is a half-answer because it is not the most efficient way to do this, and MSG_PEEK is usually employed when messages have known length headers maybe like this:

这样您就可以看到缓冲区中是否存在任意数量的字节,而不会不可逆转地读取缓冲区。这是一个半回答,因为这不是最有效的方法,MSG_PEEK通常用于消息已知长度头的时候,比如:

000123DT001    

where 00123 is the length of the whole message including header, DT is the type of message, and 001 is the number of retries by the sender. The idea is that you can fetch something that tells you how many bytes make a complete read of a message. You are not interested in messages. But that is the reason behind MSG_PEEK

其中00123是包含header的整个消息的长度,DT是消息的类型,001是发送方重试的数量。其思想是,您可以获取一些信息,这些信息告诉您一个消息的完整读取需要多少字节。你对信息不感兴趣。但这就是MSG_PEEK背后的原因。

#4


2  

You have to try send and receive command as well as you are able to read and write in socket character by character so no wastage of memory and even better communication.

您必须尝试发送和接收命令,同时您还能够按字符读和写套接字字符,这样就不会浪费内存,甚至更好的通信。

#5


1  

You could use Non-bloking sockets, or select()/poll() for that matter. I prefer non-blocking sockets because I can do other things while waiting for new data.

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

#6


0  

i think you are trying to get many packets with single system call to reduce the overhead due to system calls.

我认为您正在尝试使用单个系统调用获取多个包,以减少系统调用带来的开销。

so u can try PACKET sockets interfaces for linux 2.4 or 2.6+ kernels try this http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt

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

#1


48  

Yes:

是的:

#include <sys/ioctl.h>

...

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

#2


3  

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.

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

#3


2  

This is a "sort of" answer: recv(char* buffer, size_t nytes, int flags) where flags is OR'ed with:

这是一种“类型”的回答:recv(char* buffer, size_t nytes, int 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.

Such that you can see if an arbitrary number of bytes exists in the buffer, without irreversibly reading the buffer. This is a half-answer because it is not the most efficient way to do this, and MSG_PEEK is usually employed when messages have known length headers maybe like this:

这样您就可以看到缓冲区中是否存在任意数量的字节,而不会不可逆转地读取缓冲区。这是一个半回答,因为这不是最有效的方法,MSG_PEEK通常用于消息已知长度头的时候,比如:

000123DT001    

where 00123 is the length of the whole message including header, DT is the type of message, and 001 is the number of retries by the sender. The idea is that you can fetch something that tells you how many bytes make a complete read of a message. You are not interested in messages. But that is the reason behind MSG_PEEK

其中00123是包含header的整个消息的长度,DT是消息的类型,001是发送方重试的数量。其思想是,您可以获取一些信息,这些信息告诉您一个消息的完整读取需要多少字节。你对信息不感兴趣。但这就是MSG_PEEK背后的原因。

#4


2  

You have to try send and receive command as well as you are able to read and write in socket character by character so no wastage of memory and even better communication.

您必须尝试发送和接收命令,同时您还能够按字符读和写套接字字符,这样就不会浪费内存,甚至更好的通信。

#5


1  

You could use Non-bloking sockets, or select()/poll() for that matter. I prefer non-blocking sockets because I can do other things while waiting for new data.

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

#6


0  

i think you are trying to get many packets with single system call to reduce the overhead due to system calls.

我认为您正在尝试使用单个系统调用获取多个包,以减少系统调用带来的开销。

so u can try PACKET sockets interfaces for linux 2.4 or 2.6+ kernels try this http://lxr.free-electrons.com/source/Documentation/networking/packet_mmap.txt

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