如何在原始套接字中丢弃传入数据包?

我在Linux下编写一个C / C ++应用程序,用于从原始套接字读取数据(对于ICMP数据包)。 问题:有没有办法丢弃所有在socket上排队的数据?

问题是,睡了一会之后,有数据在我不感兴趣的sockets上排队; 所以最好告诉套接字“忘记所有你已经caching的数据”,这样如果我进入select()/ recvfrom()循环,那么我只能得到最近收到的数据。

有没有比先进入单独的poll()/ recvfrom()循环更好的方法? 一些套接字API调用也许? 便携,甚至? 🙂

你不能只是做一个recvfrom()到一个临时缓冲区,并放弃缓冲区?

在空闲时间,可以通过将接收缓冲区大小设置为零来禁用套接字:

  int optval = 0; /* May need to be 1 on some platforms */ setsockopt(sockDesc, SOL_SOCKET, SO_RCVBUF, (char *)(&optval), sizeof(optval)); 

通过将“optval”设置为更大的缓冲区来重新启用(例如4096)。

我会建议不要睡觉。 在到达时,使用select呼叫立即处理数据。

 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数据包感兴趣。

我知道如何可靠地做到这一点的唯一方法是关闭插座。

我没有尝试过,并且由于性能方面的原因可能是完全不明智的(但是如果你的应用程序正常休眠,这可能不是问题),但是:在睡眠之前,你可能会尝试将套接字的接收缓冲区设置为一个非常小的值。 我希望这将导致套接字无法缓冲应用程序不在监听时到达的数据。 这是一个远射。

或者,也许在睡眠之后重置接收缓冲区的大小,当你准备好再次开始读取时,也可以使其冲刷。 当然,这些技巧就是这样,即使他们工作,他们肯定是不可移植的。 我只是认为我会分享这个想法,如果你有机会测试它可能会帮助你。

你可以在睡觉前做这样的事吗?

 for(n=0;n<=MAX_BUFFER_SIZE;n++) { recv_buffer[n] = 0; } 

中间件应用程序中的标准过程是具有专用线程来为IO请求提供服务,其优先级设置为高于其他应用程序线程。 当IO线程接收到一个数据包时,它将其排入应用程序层。 当应用程序有空闲时,它将下一个数据包出队。

这是TIBCO Rendezvous背后的架构,用于许多实时市场数据和企业消息传递系统。 需要注意的是,您通常需要对队列大小进行一些限制,以便OOM管理器不会收到应用程序。 IO线程和应用程序层之间的协议可以从简单的异步队列到更复杂的主题过滤,优先级列表以及支持线程池并行解码传入数据。