如何实现两个线程的并发?
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 D
。thread tt
调用了捕获数据包的函数startCap()
。
我想强调一下我的问题:我调试了程序,它停在thread tt
中的pcap_loop()
位置,直到pcap_loop()
结束。我设置参数 pcap_loop()
使其成为 运行 没有结束,因为我需要连续捕获数据包。结果是程序不会进行下一步int x = 1;
。我想 运行 int x = 1;
为 thread tt
运行。 一句话,我希望threads t
和tt
同时运行。但是程序只有运行在 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()
的地方),然后我们才能继续做事。
我编写了一个程序来使用库 "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 D
。thread tt
调用了捕获数据包的函数startCap()
。
我想强调一下我的问题:我调试了程序,它停在thread tt
中的pcap_loop()
位置,直到pcap_loop()
结束。我设置参数 pcap_loop()
使其成为 运行 没有结束,因为我需要连续捕获数据包。结果是程序不会进行下一步int x = 1;
。我想 运行 int x = 1;
为 thread tt
运行。 一句话,我希望threads t
和tt
同时运行。但是程序只有运行在 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()
的地方),然后我们才能继续做事。