【问题标题】:How to discard incoming packets in raw socket?如何丢弃原始套接字中的传入数据包?
【发布时间】:2010-09-17 13:57:43
【问题描述】:

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

问题是休眠了一段时间后,socket上有我不感兴趣的数据排队;所以最好只是告诉套接字“忘记你现在缓冲的所有数据”,这样如果我进入一个 select()/recvfrom() 循环,我只会得到最近收到的数据。

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

【问题讨论】:

    标签: linux sockets flush raw-sockets


    【解决方案1】:

    我建议不要睡觉。 Insted 使用 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 数据包感兴趣。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

        • 是的,我在 VxWorks 和 eCos 中使用它。您需要确保您的操作系统支持这些标志,但我认为这是相当标准的。
        【解决方案4】:

        你不能在临时缓冲区中执行recvfrom() 并丢弃缓冲区吗?

        【讨论】:

        • 是的,这就是我最终要做的...而不是调用 sleep(),我使用 select() 并超时,如果 select() 调用指示传入数据,则数据为使用 recvfrom() 接收并忽略,然后进行新的 select(),直到睡眠时间结束。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          我没有尝试过,出于性能原因,这可能是完全不明智的(但如果您的应用程序无论如何都处于睡眠状态,这可能不是问题),但是:您可以尝试将套接字的接收缓冲区设置为一些非常小的值睡觉。我希望这会导致套接字无法缓冲应用程序未侦听时到达的数据。这有点远。

          或者,也许在睡眠后重置接收缓冲区大小,当您准备再次开始读取时,也会导致它刷新它。当然,这些技巧仅此而已,即使它们有效,它们也肯定是不可移植的。我只是想我会分享这个想法,如果您有机会对其进行测试,它可能会对您有所帮助。

          【讨论】:

            【解决方案7】:

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

            【讨论】:

            • 在这种情况下很可能是最好的解决方案 - 至少很简单。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-07-25
            • 1970-01-01
            • 1970-01-01
            • 2011-05-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多