线程和pcap问题

时间:2011-01-01 09:35:44

标签: c++ pcap libpcap

我有一个允许用户扫描网络的GUI程序,问题是当调用pcap_loop函数时,我的GUI程序变得没有响应。(pcap_loop阻止当前线程)。

当我尝试使用pthread时,我在pcap_loop函数中遇到了一个SIGSEGV错误。为什么?就好像线程无法看到procPacket函数本身。

void procPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
    //show packets here
}
void* pcapLooper(void* param)
{
    pcap_t* handler = (pcap_t*) param;
    pcap_loop(handler, 900 ,procPacket, NULL );

}
  //some function that runs when a button is pressed  
  //handler has been opened through pcap_open_live
   pthread_t scanner;
   int t = pthread_create(&scanner,NULL,&pcapLooper, &handler );
   if(t)
   {
      std::cout << "failed" << std::endl;
   }
   pthread_join(scanner,NULL);
   //do other stuff.

2 个答案:

答案 0 :(得分:3)

我强烈建议不要使用线程,除非你绝对不得不这样做。

问题是你必须非常小心,以避免竞争条件和其他同步问题。例如,您的GUI框架库可能不希望从多个线程调用,因此您的//show packets here例程可能会使它混淆不清。

相反,我会建议,如果可能的话,从主线程中读取数据包。你没有说你正在使用哪个GUI框架;因为你正在使用C ++我会假设Qt,因为这很常见,但所有其他框架都有类似的功能。

您需要做的是:

  • 调用pcap_setnonblock()将捕获描述符置于非阻塞模式
  • 调用pcap_get_selectable_fd()获取文件描述符以监控事件
  • 使用QSocketNotifier对象(将上一步中的文件描述符作为套接字参数传递)来监视事件的文件描述符
  • 当事件触发时,调用pcap_dispatch()调度数据包
  • 为了获得最大的可移植性,还可以在计时器上调用pcap_dispatch(),因为select()在某些操作系统上的pcap套接字上不能正常工作。

(至于您的代码目前崩溃的原因 - 请注意,您可能希望将handler而不是&handler作为参数传递给pthread_create()。但只是修复它可能会导致奇怪后来不可靠 - 所以单线程几乎肯定是前进的方向!)

答案 1 :(得分:1)

你需要更少的“&amp;”。假设

pcap_t *handle = pcap_open_live(...);
使用&handle

将是pcap_t **类型,但是您的线程函数会将其强制转换(顺便说一下,转换也是无意义/冗余)到pcap_t *,这会导致未定义的行为使用它时,通常会出错。更好:

static void *pcap_looper(void *arg)
{
        pcap_t *handle = arg;

        /* etc. */

        return NULL;
}

int main(void)
{
        pcap_t *handle;
        pthread_t tid;
        int ret;

        handle = pcap_open_live(...);
        ret = pthread_create(&tid, NULL, pcap_looper, handle);
        ...
        pthread_join(tid, NULL);
        return EXIT_SUCCESS;
}