0

ユーザーがネットワークをスキャンできるようにする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.
4

2 に答える 2

3

絶対に必要でない限り、スレッドを使用しないことを強くお勧めします。

問題は、競合状態やその他の同期の問題を回避するために細心の注意を払う必要があることです。たとえば、GUI フレームワーク ライブラリはおそらく複数のスレッドから呼び出されることを想定していないため、//show packets hereルーチンが混乱を招く可能性があります。

代わりに、可能であれば、メインスレッドからパケットを読み取ることをお勧めします。どの GUI フレームワークを使用しているかはわかりません。あなたは C++ を使用しているので、Qt が非常に一般的であるため、Qt を想定しますが、他のすべてのフレームワークには同様の機能があります。

あなたがする必要があるのは:

  • pcap_setnonblock() を呼び出して、キャプチャ記述子をノンブロッキング モードにします。
  • pcap_get_selectable_fd() を呼び出して、イベントを監視するファイル記述子を取得します
  • QSocketNotifierオブジェクトを使用して(前の手順のファイル記述子をソケット パラメーターとして渡します)、イベントのファイル記述子を監視します。
  • イベントが発生したら、 pcap_dispatch() を呼び出してパケットをディスパッチします
  • 移植性を最大限に高めるには、タイマーで pcap_dispatch() も呼び出します。一部の OS では、select() が pcap ソケットでうまく機能しないためです。

(コードが現在クラッシュしている理由については、パラメータとして渡すのhandlerではなく、おそらく渡したいことに注意してください。ただし、それを修正するだけで、後で奇妙な信頼性の低下につながる可能性があります-したがって、シングルスレッドに移行することは、ほぼ確実に前進する方法です!)&handlerpthread_create()

于 2011-01-01T11:46:54.380 に答える
1

必要な「&」ははるかに少なくなります。仮定

pcap_t * handle = pcap_open_live(...);

using&handleはタイプpcap_t **になりますが、スレッド関数はそれをにキャストバックします(ちなみにキャストも無意味/冗長です)pcap_t *。これにより、使用時に未定義の動作が発生し、通常は失敗します。より良い:

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

        /*など*/

        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);
        EXIT_SUCCESSを返します。
}
于 2011-01-01T11:42:57.047 に答える