刚开始使用winpcap数据包的时候,我在抓包的时候使用了
pcap_loop(adhandle, 0, packet_handler, NULL);
这个回调函数进行抓包。同时在回调函数中分析IP地址后加入了新的线程进行分析数据包。
pthread_create(&thread[threadnum], NULL,thread, &thread_ins);
我的新线程函数大致是这样的:
void* thread(void *)
{
/*省略。。。*/
while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){
/*分析数据包的格式*/
}
}
但是无论是主线程的回调函数,还是后来新加入的线程里面,抓到的数据包都出现了大量的丢包现象。仔细查询资料后,发现winpcap的接口数据是保存在一个用户缓冲区里面的。线程并发执行的时候轮流从缓冲里面读取了数据包。导致了其他的线程无法再次读取这个数据包。因此线程越多。出现的丢包现象越严重。
正确的解决方案应该是一个线程读,其他线程去分析这个数据包。我的解决方案是去建立一个公共变量。让所有的子线程从这个变量中读取。
typedef struct thread_fen
{
u_char *packet_data;
int th[50];//标记改缓冲有没有被读取
pthread_mutex_t mut;//互斥锁
}thread_fen;//这个是公共缓冲区的定义
当新的线程被定义后,就循环从这里读取。th[]标记该数据包有没有被线程读取过。经过调试,没有发生丢包现象。