我是采用多线程进行编写的,每进行一次处理后将数据包的各字段插入到listcontrol控件中,可是当初始化后,程序运行到pcap_loop(handle,0,packet_handler,NULL)这个函数时,总是发生错误,调试窗口中显示的是内存溢出,
显示为:Debug Assertion Failed!
Program:...Ia\MY DOCUMENTS\VC++ PROJECTS\NetMonitor\Debug\NetMonitor.exe
File:appcore.cpp
Line:85For information on how your program can cause an assertion
failure,see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
单步调试时,程序并不执行packet_handler函数。
由于我是初学VC,对于这方面的问题不是太清楚,怀疑是多线程方面出错了,请大家帮忙看看。部分代码如下:
//包处理函数
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
CNetMonitorApp theApp;
u_int ip_len;
u_short sport,dport;
CString strsport,strdport;
udp_header *uh = NULL;
tcp_header *th = NULL;
char buffer[256];
CString strSourseIp,strDesIP ;
CString strPackageSize; CNetMonitorDlg *pDlg = (CNetMonitorDlg*)theApp.m_pMainWnd;
int index = pDlg->m_DisList.InsertItem(0,"hello"); //获取协议类型
memset(buffer,0,256);
sprintf(buffer,"0x%02X%02X",pkt_data[12],pkt_data[13]);    if(strcmp(buffer,IP)==0)
{
    //找到IP头的位置
ip_header *ih=(ip_header *)(pkt_data+14);
switch(ih->proto)
{
case TCP:
strcpy(buffer,"TCP");
//取TCP头位置
ip_len = (ih->ver_ihl & 0xf) * 4;
th = (tcp_header *)((u_char *)ih + ip_len);
//从网络字节顺序转到主机字节顺序
sport = ntohs(th->sport);
dport = ntohs(th->dport);
strsport.Format("%d",sport);
strdport.Format("%d",dport);
            
            //显示源和目的端口
pDlg->m_DisList.SetItem(index,2,LVIF_TEXT,strsport, 0, 0, 0,0);
pDlg->m_DisList.SetItem(index,4,LVIF_TEXT,strdport, 0, 0, 0,0);
            th = NULL;
break;
case UDP:
strcpy(buffer,"UDP");
ip_len = (ih->ver_ihl & 0xf) * 4;
uh = (udp_header *) ((u_char*)ih + ip_len);      //将端口信息从网络型转变为主机顺序 
sport = ntohs( uh->sport );
dport = ntohs( uh->dport );

strsport.Format("%d",sport);
strdport.Format("%d",dport);

pDlg->m_DisList.SetItem(index,2,LVIF_TEXT,strsport, 0, 0, 0,0);
pDlg->m_DisList.SetItem(index,4,LVIF_TEXT,strdport, 0, 0, 0,0); break;
default:
sprintf(buffer,"OTHER");
break; }
        //在显示框中填入协议类型
pDlg->m_DisList.SetItem(index,0,LVIF_TEXT,buffer, 0, 0, 0,0);
        
//源IP以及目的IP
strSourseIp.Format("%d.%d.%d.%d",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4);
pDlg->m_DisList.SetItem(index,1,LVIF_TEXT,strSourseIp, 0, 0, 0,0);

strDesIP.Format(" %d.%d.%d.%d",
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
pDlg->m_DisList.SetItem(index,3,LVIF_TEXT,strDesIP, 0, 0, 0,0);

//数据包大小

strPackageSize.Format("%d",header->len-54);
pDlg->m_DisList.SetItem(index,5,LVIF_TEXT,strPackageSize, 0, 0, 0,0); }
  
}UINT monitor(LPVOID param)
{
CNetMonitorDlg *pDlg = (CNetMonitorDlg *)param;
char errbuf[PCAP_ERRBUF_SIZE]; //错误代码
CString str; u_int mask;//网络接口掩码
struct bpf_program filter; //编译后过滤器表达式
char packet_filter[32]; //包过滤规则 pcap_if_t *alldevs;
pcap_if_t *d;
int i=0,inum;

/************************************************************/


/* 获得网卡的列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\\n", errbuf);
return 0L;
}

/* 打印网卡信息 */
for(d=alldevs; d; d=d->next)
{
i++;
}

if(i==0)
{
return 0L;
}

inum = pDlg->m_NICSel.GetCurSel();

if(inum < 1 || inum > i) //判断号的合法性
{
pcap_freealldevs(alldevs);
return 0L;
}

/* 找到要选择的网卡结构 */
for(d=alldevs, i=0; i< inum ;d=d->next, i++); //获取本地地址类型掩码
if(d->addresses != NULL)
mask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
//默认为C类地址
mask=0xffffff;  /*********************************************************************/ //打开网络设备,混杂模式,读超时为0.1s
if((handle=pcap_open_live(d->name,BUFSIZ,1,1000,errbuf))==NULL)
{
AfxMessageBox("无法打开网络设备");
return 0;
}

    //取得过滤规则,即要捕获的包的类型
int j=pDlg->m_PacType.GetCurSel();
switch(j)
{ case 0:
strcpy(packet_filter,"ip");
break;
case 1:
strcpy(packet_filter,"tcp and ip");
break;
case 2:
strcpy(packet_filter,"udp and ip");
break;
default:
break;
}


//获取本地地址类型掩码
if(d->addresses != NULL)
mask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
//默认为C类地址
mask=0xffffff;  //编译过滤规则
if(pcap_compile(handle,&filter,packet_filter,1,mask)==-1)
{
AfxMessageBox("编译过滤规则时出错");
return 0;
}

//设置过滤器
if(pcap_setfilter(handle,&filter)==-1)
{
AfxMessageBox("设置过滤器时出错");
return 0;
}
    
//释放网卡列表
pcap_freealldevs(alldevs);    //循环捕获并处理合乎过滤要求的包,直到错误发生
pcap_loop(handle,1,packet_handler,NULL);
    return 0;
}CWinThread *g_pMonitorThread;
//start按钮响应函数
void CNetMonitorDlg::OnStart() 
{
g_pMonitorThread = AfxBeginThread(monitor,this);
}
void CNetMonitorDlg::OnStop() 
{
    //关闭监听会话

if(g_pMonitorThread->m_hThread != NULL)
{
TerminateThread(g_pMonitorThread->m_hThread,0);
g_pMonitorThread->m_hThread = NULL;
}
}