网络协议分析课程设计发现网络中的活动主机.docx
- 文档编号:6599095
- 上传时间:2023-01-08
- 格式:DOCX
- 页数:16
- 大小:84.19KB
网络协议分析课程设计发现网络中的活动主机.docx
《网络协议分析课程设计发现网络中的活动主机.docx》由会员分享,可在线阅读,更多相关《网络协议分析课程设计发现网络中的活动主机.docx(16页珍藏版)》请在冰豆网上搜索。
网络协议分析课程设计发现网络中的活动主机
发现网络中的活动主机
发现网络中的活动主机
一设计目的
IP协议的优点是简单,但缺少差错控制和查询机制,而网际控制报文协议(ICMP具有补充IP功能的作用。
在网络管理中,常常要确定当前网络在红处于活动状态的主机,这时可以通过ICMP的回送和回送响应消息来完成这项工作。
这课程设计的目的就是编制程序,利用ICMP数据包,发现网络中的活动主机,即ping消息的请求和应答。
通过课程设计,熟悉ICMP报文的结构,对ICMP协议有更好的理解和认识,培养综合运用网络知识解决实际问题能力。
二设计要求
设计程序,其功能是发送ICMP数据包,以获取指定望段中的活动主机,并将结果显示在标准输出设备上程序的具体要求如下:
1.用命令形式运行
scanhost为程序名;start_ip为被搜索网段;end_ip为被搜索网段的结束IP地址。
如在命令行输入scanhost192.168.0.1192.168.0.100
2.输出格式
活动主机1的IP地址
活动主机2的IP地址
活动主机n的IP地址
三概要设计
3.1设计原理
本程序使用的原始套接字生成ICMP请求/应答报文来进行活动主机的探查。
这个程序使用的是回送请求和应答消息。
程序的大致思想是把ICMP的数据报类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个IP地址已经被占用的话,那么使用位于这个IP地址的主机上的TCP/IP软件就能接受到这个ICMP回送请求,从而返回一个ICMP回送请求(类型号为0)信息。
信息封装在一个IP包中,我们需要解析该IP包,从中找到ICMP数据信息,相反,如果这个IP地址没有人使用,那么发送的ICMP回送请求在设定的延时内就不可能得到响应。
3.2数据结构设计
3.1.1.IP头部数据结构
typedefstructiphdr{
unsignedintheadlen:
4;//ip头长度
unsignedintwersion:
4;//ip版本号
unsignedchartos;//服务类型
unsignedshorttotallen;//ip包总长度
unsignedshortid;//ip号
unsignedshortflag;//标记
unsignedcharttl;//生存时间
unsignedcharprot;//协议(UDPTCP)
unsignedshortchecksum;//校验和
unsignedintsourceip;//源ip
unsignedintdestip;//目的ip
}IpHeader;
3.1.2.ICMP头部数据结构
typedefstructicmphdr{
BYTEtype;//icmp类型码,回送请求的类型码为8
BYTEcode;//子类型码,保存与特定ICMP报文类型相关的细节信息
USHORTchecksum;//校验和
USHORTid;//ICMP报文id号
USHORTseq;//ICMP数据报的序列号
}Icmpheader;
3.3系统流程图
3.3.1.主流程图(图1)
3.3.2.子流程图(图2)
四详细设计
4.1.ICMP报文分析
ICMP是一种差错和控制报文协议,用于传输错误报告和控制信息。
ICMP报文分为头部和数据部分。
ICMP报文封装在IP数据报中传输。
IP报头中的类型为1时,表示报文的数据部分为ICMP报文。
虽然ICMP报文由IP报文传输,但是并不能认为ICMP是IP的上层协议,而是IP协议的有机补充。
把ICMP报文放在IP包中,是要利用IP的转发功能。
类型(TYPE)是一个字节,表示ICMP消息的类型。
代码(CODE)也是一个字节,表示报文类型的下一步信息。
校验和共有两个字节,提供对整个ICMP报文的校验和(和IP报文类型的进一步信息)。
校验和共两个字节,提供对整个ICMP报文的校验和。
按照协议的功能来分,ICMP报文可以分为
[1].ICMP差错报文
包括目的不可达报告,超时报告,参数出错报告。
[2].ICMP控制报文
包括拥塞控制和源抑制报文,路游控制和重定向报文
[3].ICMP测试报文
包括请求应答报文,时戳请求应答报文。
本课程设计就是使用ICMP请求/应答报文来测试目的主机是否存在,请求者想某特定的主机发送请求,其中包含任选的数据。
目的主机收到请求后,发送应答报文。
在同一时刻,一台机器可以同时向多台主机发送请求报文。
ICMP报文格式如图3所示,ICMP回送报文格式如下图4所示。
类型
代码
校验和
数据区(变长)
类型(8,0)码(0)
校验和
标志位
序号
任选数据
图3.ICMP报文格式图4.ICMP回应报文格式
4.2.程序功能分析
在初始化原始套接字之后,本程序就要开始在一个IP网段内寻找活动主机。
因为要寻找活动的主机可能很多,为节省时间可以采用多线程编程。
结合核心代码对程序的具体进行分析。
4.2.1使用原始套接字
为了实现发送/监听ICMP抱文,必须使用原始套接字,创建原始套接字的代码如下:
SOCKETsockraw;
sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,wsa_flag_overlapped);
在WSASocket函数中,我们使用IPPROTO_ICMP表示接受ICMP数据包,为了使用发送接受超时设置(设置SO_RCVTIMEO或SO_SNDTIMEO),必须将标志位置为WSA_FLAG_OVERLAPPED。
然后调用setsockopt函数设置读取迟延。
在setsockopt函数中,sockraw是之前创建的原始套接字,设置SOL_SOCKET表明使用基本套接字处理ICMP抱文。
设置SO_RCVTIMEO表示使用接受超时设置,SOSNDTIMEO表示使用发送超时设置,在这里,超时时间均设置为1000ms。
4.2.2定义IP头部和ICMP头部数据结构
由于socket发送/捕获的是IP包,因此要分别定义IP头部的数据结构和ICMP头部的数据结构。
IP头部的数据结构和ICMP头部的数据结构在概要设计中已有分析。
4.2.3填充并发送请求类型的ICMP报文
#defineICMP_ECHO8//请求回送
#defineDEF_PACKET_SIZE32//缺省数据报长度
#defineMAX_PACKET1024//最大数据报长度
#charicmp_data[MAX_PACKET];//ICMP数据报最大可能长度
Memset(icmp_data,0,MAX_PACKET)//将数据报清空初始化
Intdatasize=DEF_PACKET_SIZE;//ICMP数据报报文体的额缺省长度
Datasize+=sizeof(icmpHeader);//加上ICMP数据头部
icmp_header*icmp_hdr;
char*datapart;
icmp_hdr=(icmpheader*)icmp_data;
icmp_hdr->type=icmp_echo;//设置类型
icmp_hdr->id=(ushort)getcurrentthreadid();//设置其ID号为当前线程号
datapart=icmp_data+sizeof(icmpheader);//计算出ICMP数据报的数据部分
memset(datapart,'A',datasize-sizeof(icmphearder));//填入数据
((IcmpHeader*)icmp_data)->seq=0;//序列号
((IcmpHeader*)icmp_data)->check_sum=0;//先将检验和置0
((IcmpHeader*)icmp_data)->checksum=checksum(USHORT*)icmp_data,data_size);
Checksum为计算校验和的函数,设校验和初值为0,然后对数据每16位求异或,结果取反,便得校验和。
其代码如下:
unsingedlongcksum=0;
while(size>1)
{cksum+=*buffer++;
size-=sizeof(ushort);}
if(size)
{cksum+=*(uchar)buffer;}
cksum=(cksum>>16)+(cksum&0xffff);
cksum+=(cksum>>16);
return(ushort)(~cksum);
填充ICMP报文之后,应在ICMP报文之前加上IP报头并发送出去。
可调用下面的代码发送数据包。
注意,这里的dest是填入目的主机的IP地址的一个sockaddr_in数据结构,IP_STRING是目的的主机的IP地址字符串。
Structsockaddr_in_dest;
Dest.sin_family=AF_INET;
Dest.sin_addr.s_addr=inet_addr(IP_STRING);
Sendto(sockraw,icmp_data,datasize,0,(sockaddr*)&dest,sizeof(dest));
4.2.4解析数据包
如果所ping的目的主机存在,那么它会发出一个回送应答包。
这是一个IP包,受到后解析此数据包并获得其中的ICMP信息。
根据IP报头信息中的IP报头长度字段,就可以得到ICMP报文的真实地址。
ICMP数据包中的IP地址就是活动主机的IP。
代码分析如下:
#defineICMP_MIN8
#defineMAX_PING_PACKET_SIZE(MAX_PACKET+sizeof(IpHeader))
char*recvbuf=new[MAX_PING_PACKET_SIZE];
structsockaddr_indest,from,end;
intformlen=sizeof(from);
intbytes=recvfrom(sockraw,recvbuf,MAX_PACKET,0,(Structsockaddr*)&from,&fromlen)
ipheader*iphdr;
icmpheader*icmphdr;
unsignedshortiphdrlen;
iphdr=(ipheader*)buf;
iphdrlen=iphdr->headlen*4;//IP报头的长度
icmphdr=(icmpheader*)(buf+iphdrlen);//跳过IP头
//数据包太短丢弃
if(bytes if(icmphdr->type! =icmp_echo_reply)return;//ID不相符,丢弃 if(icmphdr->id! =(USHORT)getcurrentthreadid())return; //输出正在使用的IP地址 cout<<"活动主机"< 五测试结果 5.1.测试中遇到的问题 [1]找不到头文件。 因为头文件存放位置错误。 [2]变量没有定义。 因为变量没有定义和变量名书写写错。 [3]指针书写错误。 [4]宏参数列表错误。 [5]结构体指针传递错误。 Cannotcovertfrom‘structiphdr*’to‘structicmphar*ip’ Ipheader*iphdr.因为缺少成员运算符”.”。 5.2.测试结果 经反复调试,运行正常,运行结果如下(图5) 图5 六.总结与体会 实现利用ICMP发现网络上的活动主机。 通过这次课程设计,我加深了对ICMP协议的理解,巩固了课堂知识,为以后学习网络协议打下基础。 在调试过程中难免要出现一些问题,为了能够快速地确定错误的原因,尽快的排除程序逻辑错误,通常把程序错误划分为三种类型: 语法错误、运行错误和逻辑错误。 在这次网络课程设计中,也发生了这样那样的错误,如变量没有定义、缺少头文件。 通过查阅文献资料、请教老师和同学讨论,以及自己认真地分析与思考,逐一对错误进行了调试,使程序基本能正常运行,大体上符合了设计的意图和设计的要求。 由于网络协议比较抽象,比较难学,也学得不深入,何况还要把所学知识运用到实践中来,真是一大难题,所以一开始时,真是有点一筹莫展,网上查有关资料却总觉得不搭干。 通过这次课程设计,我明白做什么事都要沉得下心,在搞任何研发工作时,遇到问题沉着冷静是特别重要的,千万不能有半点浮躁的心情。 在程序的调试过程中,出现问题是正常的,关键是如何去发现问题的根源,然后去解决它。 其实写程序并不是很花时间,改错才是最花时间的的事情。 还有一点特别重要的是,在设计过程中或者是改错的过程中遇到棘手的问题时,借助网络去解决的确是一种很好的选择。 附录及源代码 1.scanhost.h #pragmapack(4) #pragmacomment(lib,"Ws2_32.lib") #definewin32_LEAN_AND_MEAN #include #include #include #include #include #include //THEIPHEADER typedefstructiphdr{ unsignedintheadlen: 4;//ip头长度 unsignedintwersion: 4;//ip版本号 unsignedchartos;//服务类型 unsignedshorttotallen;//ip包总长度 unsignedshortid;//ip号 unsignedshortflag;//标记 unsignedcharttl;//生存时间 unsignedcharprot;//协议(UDPTCP) unsignedshortchecksum;//校验和 unsignedintsourceip;//源ip unsignedintdestip;//目的ip }IpHeader; //ICMPHEADER typedefstructicmphdr{ BYTEtype;//icmp类型码,回送请求的类型码为8 BYTEcode;//子类型码,保存与特定ICMP报文类型相关的 //节信息 USHORTchecksum;//校验和 USHORTid;//ICMP报文id号 USHORTseq;//ICMP数据报的序列号 }Icmpheader; #defineICMP_ECHO8//请求回送 #defineICMP_ECHO_REPLY0//请求回应 #defineICMP_MIN8//ICMP包头长度(最小ICMP包长度) #defineSTATUS_FAILED0xFFFF//错误码 #defineDEF_PACKET_SIZE32//缺省数据报长度 #defineMAX_PACKET1024//最大数据报长度 #defineMAX_PING_PACKET_SIZE(MAX_PACKET+sizeof(IpHeader))//最大接受数据报长度 voidfill_icmp_date(char*,int);//填充ICMP包 USHORTchecksum(USHORT*,int);//校验和函数 voiddecode_resp(char*,int,structsockaddr_in*);//找到此数据报IP地址 DWORDWINAPIFindIp(LPVOIDpipaddrtemp);//线程调用子函数 2.scanhost.cpp #include"scanhost.h" WSADATAwsadata; SOCKETsockraw; structsockaddr_indest,from,end; intfromlen=sizeof(from); char*recvbuf=newchar[MAX_PING_PACKET_SIZE]; unsignedintaddr=0; longthreadnumcounter=0,threadnumlimit=20; long*aa=&threadnumcounter; voidmain(intargc,char*argv[]){ if(argc! =3){ cout<<"输入格式错误: scanhoststart_ipend_ip"< return; } if(WSAStartup(MAKEWORD(2,1),&wsadata)! =0){ cout<<"WSAStartupfailed: "< ExitProcess(STATUS_FAILED); } //创建原始套接字 sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED); if(sockraw==INVALID_SOCKET){ cout<<"WSASocket()failed: "< ExitProcess(STATUS_FAILED); } //设置读取延时 inttimeout=1000; intbread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)); if(bread==SOCKET_ERROR){ cout<<"failtosetrecvtimeout: "< ExitProcess(STATUS_FAILED); } timeout=1000; bread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)); if(bread==SOCKET_ERROR){ cout<<"failedtosetsendtimeout: "< ExitProcess(STATUS_FAILED); } memset(&dest,0,sizeof(dest)); unsignedlongstartip,endip; dest.sin_family=AF_INET; dest.sin_addr.s_addr=inet_addr(argv[1]); startip=inet_addr(argv[1]); end.sin_family=AF_INET; end.sin_addr.s_addr=inet_addr(argv[2]); endip=inet_addr(argv[2]); HANDLEhthread; while(htonl(startip)<=htonl(endip)){ if(threadnumcounter>threadnumlimit){ Sleep(5000); continue; } DWORDThreadid; sockaddr_in*pipaddrtemp=new(sockaddr_in); if(! pipaddrtemp){ cout<<"memoryallocfailed"< return; } *pipaddrtemp=dest; //创建新线程 clock_tstart; start=clock(); hthread=CreateThread(NULL,NULL,FindIp,(LPVOID)pipaddrtemp,NULL,&Threadid); longi=60000000L; while(i--) ; TerminateThread(hthread,0); InterlockedDecrement(aa); memset(&from,0,sizeof(from)); startip=htonl(htonl(startip)+1); dest.sin_addr.s_addr=startip; } while(threadnumcounter! =0){ Sleep(2000); return; } } voidfill_icmp_data(char*icmp_data,intdatasize){ Icmpheader*icmp_hdr; char*datapart; icmp_hdr=(Icmpheader*)icmp_data; icmp_hdr->type=ICMP_ECHO; icmp_hdr->id=(USHORT)GetCurrentThreadId(); datapart=icmp_data+sizeof(Icmpheader); memset(datapart,'A',datasize-sizeof(Icmpheader)); } voiddecode_resp(char*buf,intbytes,structsockaddr_in*from){ IpHeader*iphdr; Icmpheader*icmphdr; unsignedshortiphdrlen; iphdr=(IpHeader*)buf; iphdrlen=iphdr->headlen*4; icmphdr=(Icmpheader*)(buf+iphdrlen); //数据包太短丢弃 if(bytes if(icmphdr->type! =ICMP_ECHO_REPLY)return; if(icmphdr->id! =(USHORT)GetCurrentThreadId())return; cout<<"活动主机"<
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 协议 分析 课程设计 发现 中的 活动 主机