2012-10-20 31 views
10

C++具有以下函数来从套接字接收字节,它可以检查MSG_PEEK标志可用的字节数。随着MSG_PEEK“的recv”的返回值的插座可用的字节数:用C++中的'MSG_PEEK'通过'recv'获取套接字中可用的字节数

#include <sys/socket.h> 
ssize_t recv(int socket, void *buffer, size_t length, int flags); 

我需要在插座可用的字节数,而无需创建buffer(不为buffer分配内存)。这是可能的和如何?

回答

25

您要找的是ioctl(fd,FIONREAD,&bytes_available),并在windows ioctlsocket(socket,FIONREAD,&bytes_available)下。

尽管如此,操作系统并不一定能保证它会为你缓冲多少数据,所以如果你在等待非常多的数据,你会更好地阅读数据,因为它存在并存储它在你自己的缓冲区中,直到你拥有了你需要处理的东西。

要做到这一点,什么是正常进行的是你只需一次读取的块,如

char buf[4096]; 
ssize_t bytes_read; 
do { 
    bytes_read = recv(socket, buf, sizeof(buf), 0); 
    if (bytes_read > 0) { 
     /* do something with buf, such as append it to a larger buffer or 
      * process it */ 
    } 
} while (bytes_read > 0); 

如果你不想坐在那里等待数据,你应该看看selectepoll来确定数据是否准备好被读取,如果你想确保你永远不会阻塞recv,那么socket的O_NONBLOCK标志非常方便。

+0

传入的数据套接字应该是“正在进行的字节流”或“一系列TCP包”? – jondinham

+0

查看最大字节数(可以通过程序处理)会让我觉得双重工作,因为当我们实际处理数据时,我们第二次读取 – jondinham

+1

正确,这就是为什么第一种方法更可取,尽管除非你以Gbps的速度运行,那么你永远不会注意到它.. – hexist

1

在Windows上,您可以使用ioctlsocket()函数和FIONREAD标志来询问套接字有多少字节可用,而无需自己读取/查看实际字节。返回的值是recv()可以无阻塞地返回的最小字节数。在您实际拨打recv()时,可能会有更多字节到达。

+0

我在Centos Linux上 – jondinham

+2

@PaulDinh它也可以通过ioctl()在Linux和Unix上工作。 – EJP

+0

这个答案是错误的。在文档中很清楚,Windows上的FIONREAD不会阻止从'recv'返回的可用字节数。在Windows上,'recv'可以从较低层(例如过滤器和队列以及它们自己的缓冲区)提取数据,而'FIONREAD'不这样做,只检查顶层。参见[item 12](https://tangentsoft.net/wskfaq/articles/lame-list.html)。 –