发现网络中的活动主机.docx
- 文档编号:4460857
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:16
- 大小:105.71KB
发现网络中的活动主机.docx
《发现网络中的活动主机.docx》由会员分享,可在线阅读,更多相关《发现网络中的活动主机.docx(16页珍藏版)》请在冰豆网上搜索。
发现网络中的活动主机
计算机网络课程设计报告
题 目:
发现网络中的活动主机
专业班级:
计科10102班
*******
学 号:
************
同组姓名:
谭莫然、谭斌、李绥海
1.设计目标:
现在一个机房的主机已经达到了一定数量,进行网络管理时,常常需要确定当前网络中处理活动状态的主机。
本设计的目标就是编制程序,利用ICMP的回送请求和回送响应,来发现指定网段中的活动主机。
2.设计功能:
用命令行形式运行:
scanhostStart_IPEnd_IP,来发现活动主机并显示。
(注:
scanhost为程序名,Start_IP为被搜索望断的起始IP,End_IP为其终止IP。
)
显示格式形式如下粗体部分:
活动主机:
172.16.201.11
活动主机:
172.16.201.12
活动主机:
172.16.201.13
活动主机:
172.16.201.15
环境要求:
Windows95/98/2000/XP/dos下能运行,使用VC++编写程序
3.设计原理:
本设计的主体思想是使用ICMPECHO数据包来探测指定网段内的活动主机。
具体方法是:
通过简单的发送一个ICMPECHO(Type8)数据包到目标主机,如果ICMPECHOReply(ICMPtype0)数据包接受到,说明主机是存活状态。
如果没有就可以初步判断主机没有在线或者使用了某些过滤设备过滤了ICMP的REPLY。
ICMP全称InternetControlMessageProtocol,工作在OSI的网络层。
它的中文名为因特网控制报文协议。
ICMP报文要封装在IP数据报内部才能传输。
其结构如(图一)所示。
ICMP报文的格式如(图二)所示。
所有的ICMP报文的前4个字节都是一样的,但是其他字节互不相同。
其中0-7位是类型字段,8-15位是代码字段,16-31位是校验和字段。
校验和字段为2个字节,校验的范围是整个ICMP报文。
本设计仅用到类型为0和8的ICMP报文,关于这两种类型报文的具体描述详见(图三)。
类型
代码
描述
0
0
回应应答(Ping应答,与类型8的Ping请求一起使用)
8
0
回应请求(Ping请求,与类型8的Ping应答一起使用)
图三:
本设计使用的ICMP报文类型
4.设计方法:
本设计使用原始套接字生成ICMP报文来进行活动主机的探测。
设计的大体思想是把包类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个IP地址已被占用,那么使用这个IP地址的主机上的TCP/IP软件就能够接收到这个ICMP回送请求,并返回一个ICMP回送响应信息。
由于接收到的回送响应ICMP包是封装在IP包内,就需要解析该IP包,从中找到ICMP数据信息。
相反,如果这个IP地址没有人使用,那么发送的ICMP回送请求在设定的时延内就不可能得到响应。
在初始化原始套接字后,程序就要开始在一个IP网段内寻找活动主机。
由于在某网段内需要发现的主机很多,为提高效率,采用了多线程编程。
主程序和子线程的流程图分别如(图四)和(图五)所示。
5.程序流程图:
6.程序清单:
#pragmapack(4)
#pragmacomment(lib,"WS2_32.LIB")
#defineWIN32_LEAN_AND_MEAN
#include
#include
#include
#include
#include
#include
#include
//头文件
typedefstructiphdr{//IP头
unsignedintheadlen:
4;//IP头长度
unsignedintversion:
4;//IP版本号
unsignedchartos;//服务类型
unsignedshortid;//ID号
unsignedshortflag;//标记
unsignedcharttl;//生存时间
unsignedcharprot;//协议
unsignedshortchecksum;//效验和
unsignedintsourceIP;//源IP
unsignedintdestIP;//目的IP
}IpHeader;
//IP头部
typedefstructicmphdr{//ICMP头
BYTEtype;//ICMP类型码
BYTEcode;//子类型码
USHORTchecksum;//效验和
USHORTid;//ID号
USHORTseq;//ICMP数据报的序列号
}IcmpHeader;
//ICMP包头部
#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_data(char*,int);
USHORTchecksum(USHORT*,int);
voiddecode_resp(char*,int,structsockaddr_in*);
DWORDWINAPIFindIP(LPVOIDpIPAddrTemp);
//函数的申明
WSADATAwsaData;
SOCKETsockRaw;//原始套接字
structsockaddr_indest,from,end;
//dest:
搜索目的IP,
//from:
接收ICMP包的源IP
//end:
搜索终止IP。
intfromlen=sizeof(from);//接收ICMP包长度
char*recvbuf=newchar[MAX_PING_PACKET_SIZE];//接受ICMP包缓冲区
unsignedintaddr=0;//IP地址
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<<"failedtosetrecvtimeou: "< ExitProcess(STATUS_FAILED); } timeout=1000; bread=setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)); if(bread==SOCKET_ERROR) { cout<<"failedtosetsendtimeout: "< ExitProcess(STATUS_FAILED); } memset(&dest,0,sizeof(dest));//初始化dest结构 unsignedlongstartIP,endIP; dest.sin_family=AF_INET; dest.sin_addr.s_addr=inet_addr(argv[1]);//填入开始搜索IP startIP=inet_addr(argv[1]); end.sin_family=AF_INET; end.sin_addr.s_addr=inet_addr(argv[2]); endIP=inet_addr(argv[2]);//填入结束搜索IP地址 HANDLEhThread; while(htonl(startIP)<=htonl(endIP))//起始IP比结束IP小 { 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();//设置其ID号为当前线程ID号 datapart=icmp_data+sizeof(IcmpHeader);//计算ICMP数据报的数据部分 memset(datapart,'A',datasize-sizeof(IcmpHeader));//填入数据 } //ICMP数据包的填充 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<<"活动主机: "< } //返回包的解析,以及输出 USHORTchecksum(USHORT*buffer,intsize) { unsignedlongcksum=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); } //效验和的计算 DWORDWINAPIFindIP(LPVOIDpIPAddrTemp) { InterlockedIncrement(aa);//线程数目+1 charicmp_data[MAX_PACKET]; memset(icmp_data,0,MAX_PACKET);//数据报初始化 intdatasize=DEF_PACKET_SIZE;//数据报报文的缺省长度 datasize+=sizeof(IcmpHeader);//加上icmp头部长度 fill_icmp_data(icmp_data,datasize);//填充包 ((IcmpHeader*)icmp_data)->checksum=0;//效验和置零 ((IcmpHeader*)icmp_data)->seq=0;//序列号置零 ((IcmpHeader*)icmp_data)->checksum=checksum((USHORT*)icmp_data,datasize); //计算效验和后填人 Intbwrote=sendto(sockRaw,icmp_data,datasize,0,(structsockaddr*)pIPAddrTemp,sizeof(dest)); //发送数据报 intn=0; if(bwrote==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timedout"< } cout<<"sendtofailed: "< ExitProcess(STATUS_FAILED); n=1; } if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timedout"< ExitProcess(STATUS_FAILED); n=1; } if(bwrote { cout<<"Wrote"< ExitProcess(STATUS_FAILED); n=1; } intbread=recvfrom(sockRaw,recvbuf,MAX_PING_PACKET_SIZE,0,(structsockaddr*)&from,&fromlen); //数据包的接收 if(bread==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timedout"< } cout<<"recvfromfailed: "< ExitProcess(STATUS_FAILED); n=1; } if(n==0) decode_resp(recvbuf,bread,&from); InterlockedDecrement(aa); return0; } 7.实验步骤及测试 1.建立工程sy4 2.工程中添加文件名为“scanhost”的c++头文件 3.键入头文件scanhost.h文件的内容 4.工程中添加文件名为“sy4”的c++源文件 5.键入sy4.cpp源文件的内容 6.不断调试至程序正确 7.分别编译头文件和源文件 8.连接两个文件 8.在DOS下运行可执行文件“sy4.exe” 在DOS环境下发命令如下: c: \sy4\debug\sy4172.16.201.11172.16.201.18↙ 其中sy4.exe是可执行文件。 后面的两个参数表示起始和结束IP地址。 程序执行后可从屏幕中看到所探测到的网段中活动主机的IP地址。 运行结果: (测试了172.16.201.11到172.16.201.18网段,发现主机无误) 8.总结: 计算机网络是一门新兴的交叉学科,涉及计算机技术与通信技术两个学科。 网络技术经过多年发展,已经形成比较完善的体系。 而且,网络技术还在高速发展中,其应用广泛,知识更新飞快。 对于设计这样一个发展迅速的领域来说,我们课程设计的意义更加重大。 本课程设计主要提高了我两个方面的能力: 1,真正理解和掌握处理网络问题的基本方法;2,培养了我在网络环境下的编程能力。 通过本次课程设计,我掌握了正确解读网络协议的一般方法,懂得了使用C++实现协议并实现指定功能。 通过两个星期的辛勤劳动,我较好接受了网络问题处理的基本思路,掌握网络环境中编程的基本方法。 这让我能够更好的接受前人的眼界成果,并在此基础上很好的接受新知识和继续学习,适应网络技术的飞快发展。 以上总结是宏观方面的意义。 微观上,本次实验让我很好的理解了ICMP报文的结构,对ICMP协议也有了更好的认识。 实验过程中,我充分感受到了认真严谨的重要性。 比如一次输入失误,把CreateThread写为CreateThead,虽然仅有一个r的差别,但是多花了一个多小时的调试时间。 这个意外也让我吸取了教训,编写程序的时候应该规范,认真。 实验历时两周,期间遇到了各类问题若干。 在此向给我帮助的老师和同学致以深深的谢意。 没有你们的帮忙,我不可能如此顺利的完成本设计。 9.参考资料: [1]吴功宜;计算机网络;清华大学出版社。 [2]吴功宜 胡晓英等编著;计算机网络课程设计;机械工业出版社。 [3]揣锦华;面向对象程序设计与VC++实践;西安电子科技大学出版社。 [4]高传善;数据通信与计算机网络;高等教育出版社。 [5]互连网;ICMP协议简介;http: //www.opendigest.org/article.php/65。 [6]互连网;透析ICMP协议; [6]互连网;WinSock网络编程实用宝典;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 发现 网络 中的 活动 主机