libpcap:实时使用pcap_get_selectable_fd返回的文件描述符



我正在使用libevent为一个网络程序编程。

在这个程序中,我想使用libpcap捕获数据包,修改这些数据包,然后将它们发送出去。这些步骤应该是实时的。

因此,我创建了一个实时捕获,使用pcap_get_selectable_fd获取实时捕获的文件描述符pcap_fd,并将pcap_fd的READ_EV事件添加到libevent循环中。无论如何,这就像select()或epoll()轮询文件描述符一样。

但我注意到程序没有按预期工作,所以我使用tcpdump和一些调试日志来检查问题。我注意到,有时pcap_fd上的轮询工作不正常,例如,在一开始,它似乎工作得很好。一段时间后,pcap_fd的READ_EV事件在2秒后触发,这确实是一个很大的延迟。

我读了手册,上面写着:

   pcap_get_selectable_fd(3) will return a file descriptor. But simple select() 
   or poll() will not indicate that the  descriptor  is  readable
   until  a  full  buffer's worth of packets is received, even if the read
   timeout expires before then.  

在我看来,实时捕获已经捕获了大约15个数据包(每个数据包为66字节),但READ_EV事件直到2秒后才触发。但在一开始,即使一个数据包到达也可能触发READ_EV事件。这意味着它非常不稳定。

   To work around this, an application  that
   uses  select()  or  poll()  to  wait for packets to arrive must put the
   pcap_t in non-blocking mode, and must  arrange  that  the  select()  or
   poll()  have a timeout less than or equal to the read timeout, and must
   try to read packets after that timeout expires, regardless  of  whether
   select() or poll() indicated that the file descriptor for the pcap_t is
   ready to be read or not.

我的问题是针对上面的一段:

1在我看来,有两个超时,一个是读取超时,另一个是我自己定义的超时,那么什么是读取超时?

2在我看来,我需要设置一个非常小的超时,并使用pcap_next()pcap_dispatch轮询实时捕获,对吗?那么我的轮询可能非常消耗CPU?

谢谢

有问题的段落可能是

请注意,在大多数BSD(包括Mac OS X)的大多数版本上,请选择()和poll()在BPF设备上不能正确工作;pcap_get_selectable_fd()将在大多数版本(FreeBSD 4.3和4.4除外),一个简单的select()或poll()即使在中指定的超时之后也不会返回pcap_open_live()过期。为了解决这个问题使用select()或poll()来等待数据包到达。必须将pcap_t处于非阻塞模式,并且必须安排select()或poll()的超时值小于或等于中指定的超时值pcap_open_live(),并且必须在超时后尝试读取数据包过期,无论select()或poll()是否指示pcap_t的文件描述符是否可以读取。(这项工作around将无法在FreeBSD 4.3及更高版本中工作;但是,在FreeBSD 4.6中稍后,select()和poll()在BPF设备上正常工作,因此虽然没有害处,但没有必要采取变通措施。)

你没有引用第一句话,这在这里很重要——你说的是"epoll()",这是一个Linux系统调用;该段不适用于Linux。

(pcap_get_selectable_fd手册页中该段的当前版本为

   Note that in:
          FreeBSD prior to FreeBSD 4.6;
          NetBSD prior to NetBSD 3.0;
          OpenBSD prior to OpenBSD 2.4;
          Mac OS X prior to Mac OS X 10.7;
   select()   and   poll()   do   not   work  correctly  on  BPF  devices;
   pcap_get_selectable_fd() will return a file descriptor on most of those
   versions  (the  exceptions  being  FreeBSD  4.3  and 4.4), but a simple
   select() or poll() will not indicate that the  descriptor  is  readable
   until  a  full  buffer’s worth of packets is received, even if the read
   timeout expires before then.  To work around this, an application  that
   uses  select()  or  poll()  to  wait for packets to arrive must put the
   pcap_t in non‐blocking mode, and must  arrange  that  the  select()  or
   poll()  have a timeout less than or equal to the read timeout, and must
   try to read packets after that timeout expires, regardless  of  whether
   select() or poll() indicated that the file descriptor for the pcap_t is
   ready to be read or not.  (That workaround will not work in FreeBSD 4.3
   and  later; however, in FreeBSD 4.6 and later, select() and poll() work
   correctly on BPF devices, so the workaround isn’t  necessary,  although
   it does no harm.)

这是更正确的。然而,请注意,由于Mac OS X 10.6的BPF中的一个错误,非阻塞模式无法正常工作,因此该解决方法在OS X 10.6上也不起作用。在10.7及更高版本中没有必要。)

如果使用libevent,则应将pcap_fd置于非阻塞模式,使用pcap_setnonblock()NOTfcntl()!),如果获得READ_EV事件,则使用pcap_dispatch()处理数据包。

相关内容

  • 没有找到相关文章

最新更新