程序在没有加入全局缓冲队列和多线程操作时,程序运行稳定。加入全局缓冲队列和多线程操作后,也添加了互斥体防止子线程和主线程同时对全局队列进行读写操作。
新版本在2003 ServerR2运行正常
但是在XP中却运行一段时间后就会报错。"0x0040c00d"指令引用的“0x00000010”内存。该内存不能为read。
下面是较之前稳定版 新加有关队列和线程的代码。之前稳定版本对数据包的操作都在回调函数里面完成。现在是回调函数把数据包信息保存在全局队列里,子线程不断从全局队列中取出数据包信息进行分析。
希望知道问题出在哪里?如何解决?
(如果我给出的信息不够,请说明,我会尽量补全)
#difine ETH_ALEN 6
#include <queue>
std::queue<pd> currentdata;
Thread_h th_caphand;
extern bool ifrun;
u_int8_t suscount = 0;
HANDLE hmutex;
typedef struct
{
struct EtherHeader eh;
struct IpHeader iph;
} Packet_Hdr;
typedef struct
{
time_t ltime;
u_int16_t tot_len;
u_int32_t saddr;
u_int32_t daddr;
u_int8_t ether_shost[ETH_ALEN];
u_int8_t ether_dhost[ETH_ALEN];
}pd;
//类的申明
class LabTrafficSniffer
{
public:
LabTrafficSniffer( LabTrafficMeter *meter );
bool PrepareSniff( const char *adapter, const IpFilter filter[], int num, bool filter_dns,
u_int32_t &ip, char err[ERRBUF_SIZE] );
bool Sniff(void);
void BreakSniff(void);
~LabTrafficSniffer();
private:
LabTrafficSniffer(void);
//内容处理器
static void cap_handler( LabTrafficSniffer* ts, const struct pcap_pkthdr* pkt_header, const Packet_Hdr* pkt_data );
static CALL_BACK cap_hand_routine(LabTrafficSniffer* ts);
LabTrafficMeter *meter_;
pcap_t *caphandle_;
u_int8_t ether_[ETH_ALEN];
u_int32_t subnet_ip_;
u_int32_t subnet_mask_;
};
//包含回调函数的成员函数
bool LabTrafficSniffer::Sniff(void)
{
bool succ = true;
if( caphandle_ == NULL ) return false;
hmutex = CreateMutex( NULL, TRUE, NULL );//创建互斥体
ReleaseMutex( hmutex );//释放互斥体
th_caphand = CreateThread( NULL, 0, reinterpret_cast<ThreadRoutine>(cap_hand_routine), this, 0, NULL );
// WinPcap在这循环抓包
switch( pcap_loop( caphandle_, -1, reinterpret_cast<pcap_handler>(cap_handler), reinterpret_cast<u_char*>(this) ) )
{
case -1:
{// error
succ = false;
}break;
case -2:
{// pcap_breakloop called
}break;
default:break;
}//end switch
pcap_close( caphandle_ );
caphandle_ = NULL;
return succ;
}
//回调函数
void LabTrafficSniffer::cap_handler( LabTrafficSniffer* thissnif, const struct pcap_pkthdr* pkt_header, const Packet_Hdr* pkt_data )
{
pd tempd;
//取出需要的数据包信息
tempd.ltime = pkt_header->ts.tv_sec;
tempd.tot_len = pkt_data->iph.tot_len;
tempd.daddr = pkt_data->iph.daddr;
tempd.saddr = pkt_data->iph.saddr;
memcpy(tempd.ether_dhost, pkt_data->eh.ether_dhost, 6*sizeof(u_int8_t));
memcpy(tempd.ether_shost, pkt_data->eh.ether_shost, 6*sizeof(u_int8_t));
WaitForSingleObject( hmutex, INFINITE );//等待互斥体
//将数据包信息压入缓冲队列队尾
currentdata.push(tempd);
ReleaseMutex( hmutex );//释放互斥体
if (1 == suscount) //若线程被挂起状态,则恢复线程
{
suscount--;
ResumeThread(th_caphand);
}
}
//子线程函数
CALL_BACK LabTrafficSniffer::cap_hand_routine(LabTrafficSniffer* ts)
{
while (ifrun)
{
if (!currentdata.empty())
{
pd tempad;
tempad = currentdata.front();
WaitForSingleObject( hmutex, INFINITE );//等待互斥体
currentdata.pop();
ReleaseMutex( hmutex );//释放互斥体
u_int32_t pkt_len = ntohs( tempad.tot_len );
if( (tempad.daddr & ts->subnet_mask_) == ts->subnet_ip_ )
{// 数据包是下载。Count是meter_对象的成员函数
ts->meter_->Count( tempad.ether_dhost, tempad.daddr, pkt_len, true, tempad.ltime );
}
else if( (tempad.saddr & ts->subnet_mask_) == ts->subnet_ip_ )
{// 数据包是上传。Count是meter_对象的成员函数
ts->meter_->Count( tempad.ether_shost, tempad.saddr, pkt_len, false, tempad.ltime );
}
}
else
{
suscount++;
SuspendThread(th_caphand);
}
}
return 0;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!