如何实现两个线程的并发?

How to achieve the concurrency of two threads?

我编写了一个程序来使用库 "Winpcap" 捕获数据包。 (如何用 VS2010 编译 WinPcap?请看这个link:http://www.rhyous.com/2011/11/12/how-to-compile-winpcap-with-visual-studio-2010/

我想捕获数据包(使用pcap_loop()),同时我在同一个函数void D中处理数据包。函数[=14=中的代码int x = 1; ]只是一个简单的例子,它代表了一些可以处理数据包的函数。thread t调用了void Dthread tt调用了捕获数据包的函数startCap()

我想强调一下我的问题:我调试了程序,它停在thread tt中的pcap_loop()位置,直到pcap_loop()结束。我设置参数 pcap_loop() 使其成为 运行 没有结束,因为我需要连续捕获数据包。结果是程序不会进行下一步int x = 1;。我想 运行 int x = 1;thread tt 运行。 一句话,我希望threads ttt同时运行。但是程序只有运行在 thread tt 上没有跳出和 运行 在 thread t.

PS 1:int x = 1;void D 中保持更好的状态。

PS 2:编译调试无错误。但是程序落入了thread tt.

中的函数pcap_loop

我的问题表达清楚了吗?

整个代码:

Data.h

#ifndef DATA_H
#define DATA_H

#include <pcap/pcap.h>
#include <vector>

using namespace std;

struct PcapDevice
{
    string name;
    string description;
};

class Data 
{

public:
    Data();
    ~Data();
    bool findDevices(vector<PcapDevice> &deviceList );
    bool openDevices(const char * device);
    void processPacket();
    void startCap();

private:
    pcap_t*         inData;
    char            errbuf[256];
    bool            isCapturing;
    pcap_if_t *     m_pDevs;
};

#endif // DATA_H

Data.cpp

    #include "Data.h"
    #include <iostream>

    // define pcap callback
    void capture_callback_handler(unsigned char *userData, const struct pcap_pkthdr* pkthdr, const unsigned char * packet)
    {
        ((Data*) userData)->processPacket();
    }

    Data::Data()
    {
        memset(errbuf,0,PCAP_ERRBUF_SIZE);
        isCapturing = false;
        inData = NULL;
        m_pDevs = NULL;
    }

    Data::~Data()
    {

    }

    // process the packet
    void Data::processPacket()
    {

    return ; 
    }
    // find local adapter
    bool Data::findDevices(vector<PcapDevice> &deviceList )
    {
        m_pDevs = NULL;

        int res = pcap_findalldevs(&m_pDevs, errbuf);
        if(0 == res)
        {
            pcap_if_t * pIter = m_pDevs;

            while(pIter != NULL)
            {
                PcapDevice device;
                device.description = pIter->description;
                device.name = pIter->name;
                deviceList.push_back(device);
                pIter = pIter->next;
            }
            return true;
        }
        else
        {
             printf("PCAP: no devices found\n");
        }

        return false;
    }
    // open the adapter
    bool Data::openDevices(const char *device)
    {   

        if ( (inData = pcap_open_live(device, 8192, 1,  512, errbuf)) == NULL)
        {

            return false;
        }

        return true;
    }
    // start the process of capturing the packet
    void Data::startCap()
    {
        if  ( inData == NULL ){
            fprintf(stderr, "ERROR: no source set\n" );
            return;
        }
        // free the list of device(adapter) 
        pcap_freealldevs(m_pDevs);
        Data* data = this;
        isCapturing = true;
        // capture in the loop
        if ( pcap_loop(inData, -1, capture_callback_handler, (unsigned char *) data) == -1)
        {
            fprintf(stderr, "ERROR: %s\n", pcap_geterr(inData) );
            isCapturing = false;
        }
    }

main.cpp

#include <WinSock2.h>
#include <Windows.h>
#include <time.h>
#include "Data.h"
#include <boost\thread\thread.hpp>
#include <boost\function.hpp>

struct parameter
{
   Data* pData;
};
void D(void* pParam)
{
    // init the parameter 
    parameter* pUserParams = (parameter*)pParam;
    boost::function<void()> f;
    // the capture thread will be started
    f = boost::bind(&Data::startCap, pUserParams->pData);   
    boost::thread tt(f);
    tt.join();

   // I want to work on the packet at the same time,  the code "int x=1" is only an easy example  
   // and it represents a series of functions that can process the packet. I want to run those function as the thread tt runs. 
    int x = 1;
}


void main()
{
   Data oData;
   parameter pPara ;
   pPara.pData = &oData;
   std::vector<PcapDevice>    DevList;  
   oData.findDevices(DevList);
   int num = DevList.size()-1;
   oData.openDevices(DevList[num].name.c_str());
   boost::thread t(D,(void*)&pPara);
   t.join();
}

调用tt.join()会等到线程完成(即startCap()returns)后才执行下一条语句。

您可以简单地将 int x = 1; 放在 join() 之前;但是,线程可能在那时甚至还没有启动。如果你想确保线程是 运行,或者在处理 int x = 1; 之前达到某个点,你可以使用 condition_variable:

The condition_variable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until:

  • a notification is received from another thread
void Data::startCap(std::condition_variable& cv)
{
    if  ( inData == NULL ){
        fprintf(stderr, "ERROR: no source set\n" );
        return;
    }
    // free the list of device(adapter) 
    pcap_freealldevs(m_pDevs);
    Data* data = this;
    isCapturing = true;

    // Notify others that we are ready to begin capturing packets
    cv.notify_one();

    // capture in the loop
    if ( pcap_loop(inData, -1, capture_callback_handler, (unsigned char *) data) == -1)
    {
        fprintf(stderr, "ERROR: %s\n", pcap_geterr(inData) );
        isCapturing = false;
    }
}

void D(void* pParam)
{
    // init the parameter 
    parameter* pUserParams = (parameter*)pParam;

    // Create conditional_variable
    std::conditional_variable cv;

    // Pass the conditional_variable by reference to the thread
    boost::thread tt(&Data::startCap, pUserParams->pData, std::ref(cv));
    // Wait until the thread notifies us it's ready:
    cv.wait();

    // Process packets etc.
    int x = 1;

    // Wait for the thread to finish
    tt.join();
}

现在 D() 将启动线程 tt,然后等到 startCaps 到达某个点(它调用 notify_one() 的地方),然后我们才能继续做事。