我正在Linux下编写一个C / C ++应用程序,它从原始套接字读取数据(用于ICMP数据包)。问题:有没有办法丢弃仍然在套接字上排队的所有数据?
问题是睡眠一段时间后,套接字上排队的数据我不感兴趣;所以最好告诉套接字“忘记你现在缓冲的所有数据”,这样如果我进入select()/ recvfrom()循环,那么我只得到最近收到的数据。
有没有比先进入单独的poll()/ recvfrom()循环更好的方法?有些socket API调用可能吗?便携式,甚至? : - )
答案 0 :(得分:5)
在空闲时间,您可以通过将接收缓冲区大小设置为零来禁用套接字:
int optval = 0; /* May need to be 1 on some platforms */
setsockopt(sockDesc, SOL_SOCKET, SO_RCVBUF, (char *)(&optval), sizeof(optval));
通过将“optval”设置为更大的缓冲区(例如4096)来重新启用。
答案 1 :(得分:2)
我建议不要睡觉。使用选择呼叫进行检查,以便在数据到达时立即处理数据。
while (1)
{
FD_ZERO (&sockets);
FD_SET (raw_socket, &sockets);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (select (raw_socket + 1, &sockets, NULL, NULL, &timeout))
{
if (FD_ISSET (raw_socket, &sockets))
{
// handle the packet
}
}
else
{
/* Select Timed Out */
fprintf(stderr, "Timed out");
}
}
此外,在创建原始套接字时,您可以指定您只对icmp数据包感兴趣。
答案 2 :(得分:1)
我知道如何可靠地做到这一点的唯一方法是关闭套接字。
答案 3 :(得分:1)
你不能只将recvfrom()
放入临时缓冲区并丢弃缓冲区吗?
答案 4 :(得分:0)
我没有尝试过,出于性能原因可能完全不明智(但是如果你的应用程序无论如何都会睡觉,那可能不是问题),但是:你可能会尝试将套接字的接收缓冲区设置为一些非常小的值睡觉。我希望这会导致套接字无法缓冲应用程序未侦听时到达的数据。这是一个很长的镜头。
或者,可能在睡眠后重置接收缓冲区大小,当您准备再次开始读取时,也会使其刷新。当然,这些技巧就是这样,即使它们起作用,它们肯定也不是便携式的。我只是觉得我会分享这个想法,如果你有机会测试它可能对你有所帮助。
答案 5 :(得分:0)
你可以在睡觉之前做这样的事吗?
for(n=0;n<=MAX_BUFFER_SIZE;n++)
{
recv_buffer[n] = 0;
}
答案 6 :(得分:0)
中间件应用程序中的标准过程是使用专用线程来为IO请求提供服务,其优先级设置为高于其他应用程序线程。当IO线程收到数据包时,它会将其排入应用程序层。当应用程序有空闲时间时,它会使下一个数据包出列。
这是TIBCO Rendezvous背后的架构,用于许多实时市场数据和企业邮件系统。需要注意的是,您通常需要对队列大小进行一些限制,以便OOM管理器无法获取应用程序。 IO线程和应用程序层之间的协议可以从简单的异步队列到更复杂的主题过滤,优先级列表以及支持线程池来并行解码传入数据。