我想知道在我的TCP套接字上有多少字节是可读的。我用标志“FIONREAD”调用ioctl,它实际上应该给予我这个值。当我调用函数时,我得到的是返回值0(所以没有错误),但我的整数参数也得到了值0。这将是没有问题的,但当我调用recv()我实际上从套接字中读取了一些数据。我做错了什么?
//下面是一些代码:
char recBuffer[BUFFERLENGTH] = {0};
int bytesAv = 0;
int bytesRead = 0;
int flags = 0;
if ( ioctl (m_Socket,FIONREAD,&bytesAv) < 0 )
{
// Error
}
if ( bytesAv < 1 )
{
// No Data Available
}
bytesRead = recv(m_Socket,recBuffer,BUFFERLENGTH,flags);
字符串
当我调用recv函数时,我实际上读取了一些有效的数据(这是我所期望的)
4条答案
按热度按时间sy5wg1nm1#
它发生得非常快,这就是为什么你什么也看不见。你在做什么:
ioctl
:有我的数据吗?* 没有,还没有 *recv
:阻塞,直到有数据给我。一些(短)时间后:* 这是您的数据 *所以如果你真的想看
FIONREAD
,就等着吧。字符串
vnzz0bqm2#
这里的真实的答案是像cnicutar说的那样使用select(2)。Toby,你不明白的是你有一个竞争条件。首先你看一下套接字,并询问那里有多少字节。然后,当你的代码正在处理“这里没有数据”块时,字节正在被硬件和操作系统异步接收到你的应用程序。所以,当recv()函数被调用时,“没有字节可用”的答案不再为真...
字符串
当然,两年前的一个小睡眠可能修复了你的程序,但它也教会了你糟糕的编码实践,你失去了一个学习如何使用select()正确使用套接字的机会。
此外,正如Karoly Horvath所说,您可以告诉recv不要读取超过用户传入的缓冲区中可以存储的字节数。然后您的函数接口变为“This fn will return as many bytes as are available on the socket,but not more than [buffer size you passed in]"。
这意味着该函数不再需要担心清除缓冲区,调用者可以根据需要多次调用您的函数以清除其中的所有字节(或者,您可以提供一个单独的fn,该fn将大规模丢弃数据,而不将该功能绑定到任何特定的数据收集功能中)。你的函数不需要做太多的事情,因此更加灵活。然后你可以创建一个 Package 器函数,它可以智能地满足特定应用程序的数据传输需求,而这个fn会根据需要调用get_data fn和clear_socket fn。现在,你正在构建一个库,你可以从一个项目带到另一个项目,如果你很幸运,有一个雇主允许你随身携带代码的话,你还可以从一个工作带到另一个工作。
nbysray53#
使用select(),ioctl(FIONREAD),recv()
z0qdvdin4#
你没有做错什么,如果你使用阻塞I/O recv()将阻塞,直到数据可用。