计算机网络课设报告解析ARP数据包含C++源码.docx
《计算机网络课设报告解析ARP数据包含C++源码.docx》由会员分享,可在线阅读,更多相关《计算机网络课设报告解析ARP数据包含C++源码.docx(16页珍藏版)》请在冰点文库上搜索。
计算机网络课设报告解析ARP数据包含C++源码
课程设计任务书
学院
计算机科学与技术学院
专业
通信工程
学生姓名
学号
设计题目
解析ARP数据包
内容及要求:
1.本课程以教师讲授和学生自学同步的方式进行,学校可提供上机操作,提高实际操作,设计能力。
主要功能为设计程序,实现程序
2.在完成基本技巧的讲解后,学号尾号相同的同学自行分成一组,布置不同的题目。
学生独立完成
3.教师面对面当场检查学生掌握程序情况,根据学生的学习情况及题目的完成情况评定成绩。
进度安排:
第一阶段:
在学校计算机房掌握VisualC++6.0的基本使用。
第二阶段:
学生自己解决上机,安装软件,自己在杂志,专业资料上参考,完成调试运行并打印出来,添加封面,完成课程设计。
指导教师(签字):
年月日
学院院长(签字):
年月日
1.课程设计目的………………………………………2
2.课程设计要求………………………………………2
3.相关知识………………………………………………2
1)ARP数据报的消息格式……………………3
2)ARP协议的工作流程………………………..4
4.课程设计分析……………………………………….5
1)课程设计中的重点及难点………………..5
2)参考算法………….……………………………….6
3)核心代码…………………………………………..7
5.相关扩展………………………………………………8
6.心得体会………………………………………………10
7.参考文献………………………………………………11
一、课程设计目的:
本课程设计的目的是对网络上的ARP数据包进行解析,从而熟悉ARP数据包的结构,对ARP协议有更好的理解和认识。
二、课程设计要求:
通过编制程序,获取网络中的ARP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。
程序的具体要求如下所示:
1,以命令行的形式运行,如下所示:
arpparselogfile其中,arpparse为程序名;logfile为日志文件名。
2,程序输出内容如下所示:
源IP地址 源MAC地址 目的IP地址 操作 时间
各部分的说明如下所示:
源IP地址:
输出ARP消息格式中的源IP地址字段
源MAC地址:
输出ARP消息格式中的源物理地址字段
目的IP地址:
输出ARP消息格式中的目的IP地址字段。
目的MAC地址:
输出ARP消息格式中的目的物理地址字段
操作:
输出ARP消息格式中的操作字段,若为ARP请求,则为1,若为ARP应答,则为2,
时间:
该ARP包产生的时间
3,当程序接收到键盘输入Ctrl+C时字段
三、相关知识
a)ARP数据报的消息格式
网络上的每台主机或设备都有一个或多个IP地址。
IP地址是网络层的地址,在网络层,数据被组装成IP包。
但是发送IP包需要物理设备的支持(通常是Ethernet设备,在本课程设计中我们指定为Ethernet设备),即发送端必须知道目的物理地址才能将IP包发送出去,所以需要一种将IP地址映射为物理地址的机制。
ARP协议就是用来完成这个任务的。
ARP协议能够在同一个物理网络中,在给定目的主机或设备的IP地址的条件下,得到目的主机或设备的物理地址。
ARP协议的数据包格式如图所示:
08162431(位)
硬件类型
协议类型
物理地址长度
协议地址长度
操作
源物理地址(八位组0~3)
源物理地址(八位组4~5)
源IP地址(八位组0~1)
源IP地址(八位组2~3)
目的物理地址(八位组0~1)
目的物理地址(八位组2~5)
目的IP地址(八位组0~3)
ARP数据包的消息格式
下面对数据包的各个部分进行说明
●硬件类型:
指定硬件接口类型。
例如,值为1表示Ethernet
●协议类型:
指定发送方支持的上层协议的类型
●物理地址长度:
指定物理(硬件)地址的长度
●协议地址长度:
网络层协议的地址长度。
若为IP协议,其值为4
●操作:
指定ARP的操作类型,例如,1表示ARP请求,2表示ARP应答
●源物理地址:
指定发送方的IP地址
●目的物理地址:
指定目的物理地址。
●目的IP地址:
指定目的IP地址
ARP分组必须在数据链路层中被封装成侦,才能发送出去封装形式如图所示
将ARP数据包封装成一个帧
b)ARP协议的工作流程。
1)在发送一个ARP分组之前,源主机首先根据目的IP地址,在本地ARP高速缓存表中查找与之对应的目的物理地址。
如果找到对应的物理地址,就不用进行地址解析,否则需要进行地址解析。
2)实现地址解析的第一步是产生ARP请求分组。
在相应的字段写入本地主机的源物理地址、源IP地址,在目的物理地址字段写入0,并在操作字段写入1。
3)将ARP分组发送到本地的数据链路层,并封装成帧。
以源物理地址作为源地址,以物理广播地址(FF-FF-FF-FF-FF-FF)作为目的地址,通过物理层发送出去。
4)由于采用了广播地址,因此网段内所有的主机或设备都能接受到该帧。
除了目的主机外,所有接受到该分组的主机和设备都会丢弃该分组,因为目的主机能够识别ARP消息中的目的IP地址。
5)目的主机发送ARP应答分组。
在ARP应答分组中,以请求分组中源物理地址、源IP地址作为其目的物理地址、目的IP地址,并将目的主机自身的物理地址、IP地址填入应答分组的源物理地址、源IP地址字段,并在操作字段中写入2。
该分组通过数据链路层以点对点的方式发送出去(因为现在目的方已经知道双方的物理地址)。
6)源结点接收到ARP应答分组,知道对应于目的IP地址的目的物理地址,将它作为一条新记录加入到ARP高速缓存表。
7)源结点将有完整源IP地址、源物理地址、目的IP地址、目的物理地址的信息和数据作为一个发送分组,传送给它的数据链路层并封装成桢,然后以点对点的方式发送到目的主机。
四、课程设计分析
1.课程设计中的重点及难点
1)程序中会用到Winpcap,Winpcap是Win32环境下数据包捕获的开放代码函数库。
基于Winpcap的应用程序一般按照下面几个步骤进行设计:
●输出网卡设备列表。
●选择网卡并打开。
●捕获数据包时,可能需要设置过滤器。
●捕获数据包或者发送数据包。
2)在程序设计过程中需要注意网络—主机字节顺序的转化。
由于不同的计算机系统所采用的数据表示方式不同,对于2B或4B的数据,有的采用低字节地址存放数据的高权值位,而有的却以低地址字节存放数据低权位值,在网络的数据传输中,我们应该统一表示,所以我们在捕获数据包后,应将数据包头部的表示长度或类型的数据转换成本地机的表达形式。
可以利用函数ntohs()将网络字节序转换为主机字节序。
3)选择网卡并打开时,注意选择可用的网卡。
2.参考算法
1)取得当前网卡设备列表。
2)选择Ethernet网卡并打开,注意判断所选网卡是否为实际存在的可用网卡。
3)设置过滤器,此处的过滤器正则表达式为“arp”或者“etherproto\\arp”。
4)捕获数据包并进行处理(包括输出各IP地址,物理地址,操作类型以及时间)。
由于要记录日志文件,为了便于输出流参数,建议采用pcap_next_ex()函数。
流程图如图所示:
3.核心代码
●ARP数据包结构
structarppkt{
unsignedshorthdtyp;//硬件类型。
值0001表示其为Ethernet
unsignedshortprotyp;//协议类型。
值0800表示上层协议为IP
unsignedcharhdsize;//硬件地址长度。
值为06
unsignedcharprosize;//协议地址长度。
值为04
unsignedshortop;//操作值为0001/0002,分别表示ARP请求/应答
u_charsmac[6];//源MAC地址,6B
u_charsip[4];//源IP地址,4B
u_chardmac[6];//目的MAC地址
u_chardip[4];//目的IP地址
};
●获取网络设备列表,并以混杂模式打开网络设备
//获取网络设备列表
if(pcap_findalldevs(&alldevs,errbuf)==-1)
{
cout<<"Errorinpcap_findalldevs:
"<return;
}
//选择Ethernet卡
for(d=alldevs;d;d=d->next)
{
//以混杂模式打开网卡,以接受所有的帧
if((adhandle=pcap_open_live(d->name,1000,1,300,errbuf))==NULL)
{
cout<<"\nUnabletoopentheadapter.";
pcap_freealldevs(alldevs);//释放设备列表
return;
}
if(pcap_datalink(adhandle)==DLT_EN10MB&&d->addresses!
=NULL)
break;
}
●编译过滤器并设置过滤器,只捕获ARP数据包
charpacket_filter[]=”etherproto\\arp”;//过滤,选择arp协议
if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)<0)
{cout<<"\nUnabletocompilethepacketfilter.Checkthesyntax.\n";
pcap_freealldevs(alldevs);
return;
}
//设置过滤器
if(pcap_setfilter(adhandle,&fcode)<0)
{cout<<"\nErrorsettingthefilter.\n";
pcap_freealldevs(alldevs);
return;
}
●循环捕获ARP包,并进行解析
while((result=pcap_next_ex(adhandle,&header,&pkt_data))>=0)
{
输出ARP数据包的各个域的内容到文件和屏幕上
}
●源程序
#include
#pragmacomment(lib,"Ws2_32.lib")//用到ntobs()
//等同于点击"project-setting-link"打开object/librarymodule编辑框后加入文件
#pragmacomment(lib,"wpcap.lib")
#include"pcap.h"//此头文件没有包含在VC中,需要另外加入
#include
#include//格式化输出需要用到
#include//用到_getch()
//注意到接收的数据包头中代表类型,数据长度的字段采用的是big-endian
//所以对于2B/4B的数据要用ntohs()转换为本机形式
//ARP包结构
structarppkt{
unsignedshorthdtyp;//硬件类型.值0001
unsignedshortprotyp;
unsignedcharhdsize;
unsignedcharprosize;
unsignedshortop;
u_charsmac[6];
u_charsip[4];
u_chardmac[6];
u_chardip[4];
};
voidpacket_handler(constpcap_pkthdr*header,constu_char*pkt_data,ostream&out);
voidmain(intargc,char*argv[])
{
if(argc!
=2)
{
cout<<"Usage:
arpparselogfilename"<cout<<"pressanykeytocontinue."<_getch();
return;
}
pcap_if_t*alldevs;
pcap_if_t*d;
pcap_t*adhandle;
charerrbuf[PCAP_ERRBUF_SIZE];
u_intnetmask;
charpacket_filter[]="etherproto\\arp";
structbpf_programfcode;
structpcap_pkthdr*header;
constu_char*pkt_data;
if(pcap_findalldevs(&alldevs,errbuf)==-1)
{
cout<<"Errorinpcap_findalldevs:
"<return;
}
for(d=alldevs;d;d=d->next)
{
if((adhandle=pcap_open_live(d->name,1000,1,300,errbuf))==NULL)
{
cout<<"\nUnabletoopentheadapter.";
pcap_freealldevs(alldevs);
return;
}
if(pcap_datalink(adhandle)==DLT_EN10MB&&d->addressess!
=NULL)
break;
}
if(d==NULL)
{
cout<<"\nNointerfacesfound!
MakesureWinpcapisinstalled.\n";
return;
}
//获得子网掩码
netmask=((sockaddr_in*)(d->netmask))->sin_addr.s_un.s_addr;
//编译过滤器,只捕获ARP包
if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)<0)
{cout<<"\nUnabletocompilethepacketfilter.Checkthesyntax.\n";
pcap_freealldevs(alldevs);
return;
}
//设置过滤器
if(pcap_setfilter(ashandle,&fcode)<0)
{cout<<"\nErrorsettingthefilter.\n";
pcap_freealldevs(alldevs);
return;
}
cout<<"\t\tlisteningon"<description<<"..."<//显示提示信息及每项含义
ofstreamfout(argv[1],ios:
:
app);//日志记录文件
//为了查看日志时的方便,其中加入了日期记录
time_tt;
time(&t);
fout.seekp(0,ios:
:
end);
if(fout.tellp()!
=0)
fout<fout<<"\t\tARPrequest
(1)/reply
(2)on"<cout<<<""<<"DesIpAddr"<<""<<"DesMACAddress"
<<""<<"OP"<<""<<"Time"<fout<<<""<<"DesIpAddr"<<""<<"DesMACAddress"
<<""<<"OP"<<""<<"Time"<//释放设备列表
pcap_freealldevs(alldevs);
intresult;
while((result=pcap_next_ex(adhandle,&header,&pkt_data))>=0)
{
if(result==0)
continue;
packer_handler(header,pkt_data,cout);
packet_handler(header,pkt_data,fout);
}
}
voidpacket_handler(constpcap_pkthdr*header,constu_char*pkt_data,ostream&out)
{
arpkt*arph=(arppkt*)(pkt_data+14);
for(inti=0;i<3;i++)
out<sip[i])<<'.';
out.setf(ios:
:
left);
out<sip[3])<<"";
out.unsetf(ios:
:
uppercase);
for(i=0;i<5;i++)
out<(2)<smac[i])<<'-';
out<(2)<smac[5])<<"";
out.fill(oldfillchar);
out.unsetf(ios:
:
hex|ios:
:
uppercase);
for(i=0;i<3;i++)
out<dip[3])<<'.';
out.unsetf(ios:
:
left);
//输出目的MAC地址
out.fill('0');
out.setf(ios:
:
uppercase);
for(i=0;i<5;i++)
out<(2)<dmac[i])<<'-';
out.fill(oldfillchar);
out.unsetf(ios:
:
hex|ios:
:
uppercase);
out<op)<<"";
structtm*ltime;
ltime=localtime(&header->ts.tv_sec);
out.fill('0');
out<tm_hour<<':
'<(2)<tm_min<<':
'<(2)<tm_sec;
out.fill(oldfillchar);
out<}
五、相关扩展
本课程设计还可以在Linux环境下用rawsocket完成。
算法和代码提示:
1)调用socket()打开协议簇为PF_PACKET的原始套接字,这样我们就可以收到数据链路帧:
intfd=socket(PF_PACKET,SOCK_RAM,htons(ETH_P_ALL));
2)对打开的套接字调用ioct1(),将网卡设置为混杂模式,这样我们就可以接受到局域网中所有的包(包括目的地址不是本机的帧):
structifreqreq;
memset(&req,0,sizeof(req));
strncpy(req.ifr_name,”eth0”,strlen(“eth0”)+1);
ioctl(fd,SIOCGIFFLAS,&req);
req.ifr_flags|=IFF_PROMISC;//设置为混杂模式
icotl(fd,SIOCGIFFLAGS,&req);
3)利用recvfrom()接收包:
recvform(fd,buffer,sizeof(buffer),0,(structsockaddr*)&from,&from_len);
4)接收到包后,判断是否为ARP包,若是ARP包则进行处理,否则丢弃。
If((ntohs(eth_header->ether_type)==0x0806)
&&(ntohs(arp_header->ar_hrd)==0x0001)
&&(ntohs(arp_header->ar_pro)==0x0800)
&&(arp_header->ar_hln==0x06)
&&(arp_header->ar_pln==0x04)
&&((ntohs(arp_header->ar_op)==0x01)||
(ntohs(arp_header->ar_op)==0x02)))
{
对ARP数据包进行分析并打印
}
5)算法在3、4步之间进行循环,直到强行退出为止。
六、心得体会
本次课程设计,完成了在xp环境下的解析ARP数据包。
在具体实现获取网络中的ARP数据包解析数据包的内容,并将其写入日志文件的过程中,是我更加清楚物理地址、IP地址的关联,源地址与目的地址的关系,以及二者对数据类型的格式要求。
最重要的是通过这次的实际训练让我对ARP协议更加理解。
本次课程设计查阅了大量的案例,学到了很多知识,使我对计算机网络有了更深入的了解。
我觉得这次课程设计我觉得收获挺大的。
之前的学习仅限于书本,网络的很多东西都只知道其然而不知道其所以然。
课程设计是培养我们综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对我们实际工作能力的具体训练和考察过程。
随着科学技术发展的日新月异,网络已经成为当今计算机发展中空前活跃的领域,在生活中可以说是无处不在,因此作为二十一世纪的计算机专业的大学生来说掌握网络组网技术是十分重要的。
七、参考资料
1.谢希人著.计算机网络(第四版)大连理工大学出版社2003
2.宋凯等著.计算机网络.北京:
清华大学出版社2010
3.吴功宜等著.计算机网络课程设计.北京:
机械工业出版社2005.9
4.李爱华等著.面向对象程序设计(C++语言).北京:
清华大学出版社2010
5.