从来没写过blog,今天是我的第一次写blog。尝试一下,呵呵!随便转载,转载请注明出处http://blog.csdn.net/leotangcw/
欢迎大家和我交流QQ:17371764 Email:[email protected]
本文适合初学MFC编程的同学,如果您对VC(MFC)编程不是太熟悉请您参看《VC++技术内幕》或其他的VC入门书籍。
代码写的很冗余,还用了很多全局的变量,程序写的太少,不好意思,嘿嘿!请大家多指教!
我今年7月就本科毕业了,最近做毕业设计,导师给了局域网数据包截取与分析的题目,算是中等难度的题目(对面一个兄弟做机器人避障,感觉交给本科生就不是很现实,没选,也有做个什么什么系统的,感觉太没意思,选个这个难度适中),写了两周现在算是完成了,把些心得发上来,希望能对有的朋友有帮助。
先是选捕获方法了,可以有winsocket winpacp libcap等很多捕获方式,由于我只是在windows下开发,选了winpcap+MFC的方式。
一开始是设计一个界面,主要是设置一些参数什么的,如网卡接口选择,捕获数目什么的,主要参考了Ethereal的界面设置,做了一个简单的
捕获接口,过滤器的后面是一个COMBOX,使用混杂模式等是CHECK控件,其他都是EDIT控件和SPIN控件,和STATIC放好了以后申明各个组件对应的变量。然后在类向导里面添加WM_INITDIALOG消息,在生成的函数里添加初始化代码//以下是对话框上资源的初始化
m_spacketlimit.SetBuddy(&m_epacketlimit);
m_spacketlimit.SetBase(10);
m_spacketlimit.SetRange(50,32767);
m_spacketlimit.SetPos(100);
m_sstopnum.SetBuddy(&m_estopnum);
m_sstopnum.SetBase(10);
m_sstopnum.SetRange(1,32767);
m_sstopnum.SetPos(100);
m_sstoptime.SetBuddy(&m_estoptime);
m_sstoptime.SetBase(10);
m_sstoptime.SetRange(1,32767);
m_sstoptime.SetPos(30);
m_cinpromiscuousmode=true;
//以上是对话框上复选框的初始化
UpdateData(false);
//以下是combox的初始化
pcap_if_t *alldevs;
pcap_if_t *d;
struct in_addr net_ip_address;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
if(pcap_findalldevs(&alldevs, errbuf)==-1)
{
AfxMessageBox("Error in pcap_findalldevs");
AfxMessageBox(errbuf);
}
for(d=alldevs; d; d=d->next)
{
if (d->description)
{
m_cinterface.AddString(d->description);
}
else
AfxMessageBox("No description available");
m_devnum++;
}
m_cfilter.AddString("arp");
m_cfilter.AddString("tcp");
m_cfilter.AddString("udp");
m_cfilter.AddString("port 80");
m_cfilter.AddString("ip src host 172.29.6.67");
m_cfilter.AddString("自定义过滤规则请自己添加,空白为捕获所有包");
m_exsn=0;
m_eventEnd.ResetEvent();
m_stoptimeup.ResetEvent();
然后在各个复选框的点击事件里添加类式代码,实现点击就可以允许/禁止后面的EDIT和SPIN控件的使用的目的。
UpdateData(true);
if(m_cpacketlimit)
{
GetDlgItem(IDC_EDIT_PACKETLIMIT)->EnableWindow(true);
GetDlgItem(IDC_SPIN_PACKETLIMIT)->EnableWindow(true);
}
else
{
GetDlgItem(IDC_EDIT_PACKETLIMIT)->EnableWindow(false);
GetDlgItem(IDC_SPIN_PACKETLIMIT)->EnableWindow(false);
}
UpdateData(true);
在接口选择的CHANG事件里面用如下的代码实现遍历本机的各个网卡并且添加到下拉列表里面以供选择。
m_devindex=m_cinterface.GetCurSel()+1;
pcap_if_t *alldevs;
pcap_if_t *d;
bpf_u_int32 net_mask;
bpf_u_int32 net_ip;
struct in_addr net_ip_addr;
struct in_addr net_mask_addr;
int m_count=1;
char errbuf[PCAP_ERRBUF_SIZE];
if(pcap_findalldevs(&alldevs,errbuf)==-1)
{
AfxMessageBox("Error in pcap_findalldevs");
AfxMessageBox(errbuf);
}
else
{
d=alldevs;
while(m_count
d=d->next;
m_count++;
}
}
/* 获得网络接口 */
pcap_lookupnet(d->name, &net_ip, &net_mask, errbuf);
net_ip_addr.S_un.S_addr=net_ip;
net_mask_addr.S_un.S_addr=net_mask;
m_sMask=inet_ntoa(net_mask_addr);
m_sIPAddress=inet_ntoa(net_ip_addr);
pcap_freealldevs(alldevs);
GetDlgItem(IDC_STATIC_NAME)->SetWindowText(m_sMask);
GetDlgItem(IDC_STATIC_IP)->SetWindowText(m_sIPAddress);
UpdateData(false);
主要是使用findalldevs函数得到一个网卡接口列表,你可以参考winpcap开发包,尽量不要使用lookupdev那个,我试过因为很多机器经常第一个网卡接口是一个虚拟的接口(一般看不见),如果你用lookupdev的话就会什么都得不到。在用pcap_lookupnet把网卡地址和子网掩码显示在左下角。
在浏览的按钮里添加
CFileDialog m_file_dlg(TRUE, "DAT", ".DAT", OFN_HIDEREADONLY, _T(".DAT Files|*.DAT"), this);
m_file_dlg.m_ofn.lpstrTitle="保存数据包文件";
if(m_file_dlg.DoModal() == IDOK )
{
CString pathName=m_file_dlg.GetPathName();
m_efile_path.SetWindowText(pathName);
UpdateData(true);
}
打开一个文本框,返回一个文件路径以后用。
今天就写到这吧,明天继续!
一步一步尝试在MFC下开发基于winpcap的数据包捕获和分析软件(之二):
http://blog.csdn.net/leotangcw/archive/2006/05/12/726629.aspx