版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、计算机网络课程设计一、设计内容及设计要求课程设计内容:利用ICMP数据包,通过使用ICMP的回送和回送响应消息来确定当前网络中处于活动状态的主机,即ping消息的请求和应答,将发送的ICMP的数据包类型设置为回送请求(类型号为8),并显示在标准输出上。用命令行形式运行:scanhost Start_IP End_IP,其中scanhost为程序名;Start_IP为被搜索网段的开始IP;End_IP为被搜索网段的结束IP地址。课程设计目的:IP协议的优点是简单,但缺少差错控制和查询机制,而网际控制报文协议(ICMP具有补充IP功能的作用。在网络管理中,常常要确定当前网络在红处于活动状态的主机,
2、这时可以通过ICMP的回送和回送响应消息来完成这项工作。这课程设计的目的就是编制程序,利用ICMP数据包,发现网络中的活动主机,即ping消息的请求和应答。通过课程设计,熟悉ICMP报文的结构,对ICMP协议有更好的理解和认识,培养综合运用网络知识解决实际问题能力。课程设计要求:设计程序,其功能是发送ICMP数据包,以获取指定望段中的活动主机,并将结果显示在标准输出设备上程序的具体要求如下:1用命令形式运行2输出格式活动主机1的IP地址活动主机2的IP地址活动主机 n的IP地址二、总体设计设计原理首先对ICMP报文的格式有一定的了解,ICMP报文是在IP数据报内部传输的,其结构如图所示: IP
3、数据报 IP首部 ICMP报文ICMP报文的格式如图所示:0 7 8 15 16 31(位)类型字段代码字段校验和字段(不同类型和代码有不同内容)所有报文的前4个字节都是一样的,但是其它字节则互不相同。其中类型字段可以有15个不同的值,以描述特定类型的ICMP报文,某些ICMP报文还使用代码字段的值来进一步描述不用的条件。按验和字段为2字节,校验的范围是整个ICMP报文。检验和是必须的,其计算方法与IP协议头部校验和的计算方法一样。各种类型的ICMP报文如图所示(ICMP报文类型),不同类型由报文中的类型字段和代码字段来共同决定。类 型 代 码 描 述 0 0 回送响应(PING应答)3 目的
4、不可达0 网络不可达1 主机不可达2 协议不可达3 端口不可达4 需要进行分片但设置了禁止分片比特5 源主机选择路由失败6 无法识别目的网络7 无法识别目的主机8 源主机被隔离9 目的网络被禁止10 目的主机被禁止11 由于服务类型(TOS),网络不可达12 由于服务类型(TOS),主机不可达13 由于过滤,通信被强行禁止14 主机越权15 优先权终止生效 4 0 源端被关闭(基本流控制)5 重定向0 对网络重定向1 对主机重定向2 对服务类型和网络重定向3 对服务类型和主机重定向 8 0 回送请求(PING请求)9 0 路由器通告10 0 路由器请求11 超时0 传输期间生存期减为01 数据
5、报组装期间生存期减为012 参数问题0 各种IP头部错误1 缺少必须的选项13 0 时间戳请求14 0 时间戳应答15 0 信息请求(已作废)16 0 信息应答(已作废)17 0 地址掩码请求18 0 地址掩码应答课程设计的目的是发现网络中的活动主机,就是使用ICMP的回送和回送响应消息发现网络中的活动主机,即Ping消息的请求和应答。那幺,发送的ICMP的数据包类型设置为回送请求(类型号为8)。本程序使用的原始套接字生成ICMP请求/应答报文来进行活动主机的探查。这个程序使用的是回送请求和应答消息。程序的大致思想是把ICMP的数据报类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个
6、IP地址已经被占用的话,那么使用位于这个IP地址的主机上的TCP/IP软件就能接受到这个ICMP回送请求,从而返回一个ICMP回送请求(类型号为0)信息。信息封装在一个IP包中,我们需要解析该IP包,从中找到ICMP数据信息,相反,如果这个IP地址没有人使用,那么发送的ICMP回送请求在设定的延时内就不可能得到响应。概要设计主程序流程图开 始构造原始套接字,并初始化建立并初始化木的主机的Sockaddr_in数据结构dest起始IP地址->start_ip结束IP地址->end ip将start_ip填入到dest中start_ip< = end ip? 线程数目太多?创建一
7、个线程并执行 start_ip +还有线程在执行?结 束等待一定时间NYYN等待一定时间Y子线程流程图开 始填充ICMP数据报发送数据报 接受数据报去掉IP头,获取ICMP信息数据包太短?不是回送响应?ID不符合?数据库中的IP地址结 束YYYNNN三、详细设计及代码3.1 ICMP报文分析ICMP是一种差错和控制报文协议,用于传输错误报告和控制信息。 ICMP报文分为头部和数据部分。ICMP报文封装在IP数据报中传输。IP报头中的类型为1时,表示报文的数据部分为ICMP报文。虽然ICMP报文由IP报文传输,但是并不能认为ICMP是IP的上层协议,而是IP协议的有机补充。把ICMP报文放在IP
8、包中,是要利用IP的转发功能。 类型(TYPE)是一个字节,表示ICMP消息的类型。代码(CODE)也是一个字节,表示报文类型的下一步信息。校验和共有两个字节,提供对整个ICMP报文的校验和(和IP报文类型的进一步信息)。校验和共两个字节,提供对整个ICMP报文的校验和。按照协议的功能来分,ICMP报文可以分为1. ICMP差错报文 包括目的不可达报告,超时报告,参数出错报告。2 .ICMP控制报文包括拥塞控制和源抑制报文,路游控制和重定向报文3 .ICMP测试报文包括请求应答报文,时戳请求应答报文。本课程设计就是使用ICMP请求/应答报文来测试目的主机是否存在,请求者想某特定的主机发送请求,
9、其中包含任选的数据。目的主机收到请求后,发送应答报文。在同一时刻,一台机器可以同时向多台主机发送请求报文。ICMP报文格式如图所示: 类型 代码 校 验 和 数据区(变长)ICMP回送报文格式如下图所示:类型(8,0) 码(0) 校验和 标志位 序号 任选数据程序功能分析本程序使用原始套接字生成ICMP报文来进行活动主机的探查。这个程序使用的是回送请求与应答信息。程序的大致思想是把ICMP的数据包类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个IP地址已经被占用的话,那么使用位于这个IP地址的主机上的TCP/IP软件就能够接受到这个ICMP回送请求,从而返回一个ICMP回送响应(类
10、型号为0)信息。信息封装在一个IP包中,需要解析该IP包,从中找到ICMP数据信息。相反,如果这个IP地址没有人使用,那么发送的ICMP回送请求在设定的延时内就不可能得到响应。在初始化原始套接字之后,本程序就要开始在一个IP网段内寻找活动主机。因为要寻找活动的主机可能很多,为节省时间可以采用多线程编程。结合核心代码对程序的具体进行分析。使用原始套接字为了实现发送/监听ICMP抱文,必须使用原始套接字,创建原始套接字的代码如下:SOCKET sockraw;sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,wsa_flag_overla
11、pped);在WSASocket函数中,我们使用IPPROTO_ICMP表示接受ICMP数据包,为了使用发送接受超时设置(设置SO_RCVTIMEO或SO_SNDTIMEO),必须将标志位置为WSA_FLAG_OVERLAPPED。然后调用setsockopt函数设置读取迟延。在setsockopt函数中,sockraw是之前创建的原始套接字,设置SOL_SOCKET表明使用基本套接字处理ICMP抱文。设置SO_RCVTIMEO表示使用接受超时设置,SOSNDTIMEO表示使用发送超时设置,在这里,超时时间均设置为1000ms。定义IP头部的数据结构typedef struct iphdr u
12、nsigned int headlen:4; /ip头长度 unsigned int wersion:4; /ip版本号 unsigned char tos; /服务类型 unsigned short totallen; /ip包总长度 unsigned short id; /ip号 unsigned short flag; /标记unsigned char ttl; /生存时间unsigned char prot; /协议(UDP TCP)unsigned short checksum; /校验和unsigned int sourceip; /源ipunsigned int destip;
13、/目的ipIpHeader;定义ICMP头部数据结构typedef struct icmphdr BYTE type; /icmp类型码,回送请求的类型码为8 BYTE code; /子类型码,保存与特定ICMP报文类型相关的细节信息 USHORT checksum; /校验和 USHORT id; /ICMP报文id号 USHORT seq; /ICMP数据报的序列号Icmpheader;填充并发送请求类型的ICMP报文#define ICMP_ECHO 8 /请求回送 #define DEF_PACKET_SIZE 32 /缺省数据报长度#define MAX_PACKET 1024 /最
14、大数据报长度#char icmp_dataMAX_PACKET; /ICMP数据报最大可能长度Memset(icmp_data,0, MAX_PACKET) /将数据报清空初始化Int datasize=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
15、=(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=checks
16、um(USHORT*) icmp_data,data_size);Checksum 为计算校验和的函数,设校验和初值为0,然后对数据每16位求异或,结果取反,便得校验和。其代码如下:USHORT checksum(USHORT * buffer, int size) /计算校验和unsinged long cksum=0;while (size>1)cksum+=*buffer+;size-=sizeof(ushort);if(size)cksum+=*(uchar)buffer;cksum=(cksum>>16)+(cksum&0xffff);cksum+=(cks
17、um>>16);return (ushort)(-cksum); 填充ICMP报文之后,应在ICMP报文之前加上IP报头并发送出去。可调用下面的代码发送数据包。注意,这里的dest是填入目的主机的IP地址的一个sockaddr_in数据结构,IP_STRING是目的的主机的IP地址字符串。 Struct sockaddr_in_dest; Dest.sin_family=AF_INET; Dest.sin_addr.s_addr=inet_addr(IP_STRING); Sendto(sockraw,icmp_data,datasize,0,(sockaddr*)&des
18、t,size of(dest);解析数据包如果所ping的目的主机存在,那么它会发出一个回送应答包。这是一个IP包,受到后解析此数据包并获得其中的ICMP信息。根据IP报头信息中的IP报头长度字段,就可以得到ICMP报文的真实地址。ICMP数据包中的IP地址就是活动主机的IP。代码分析如下: #define ICMP_MIN 8 #define MAX_PING_PACKET_SIZE(MAX_PACKET+sizeof(IpHeader) char *recvbuf=newMAX_PING_PACKET_SIZE; struct sockaddr_in dest,from,end;int f
19、ormlen=sizeof(from); int bytes=recvfrom(sockraw,recvbuf,MAX_PACKET,0,(Struct sockaddr*)&from,&fromlen) ipheader *iphdr; icmpheader *icmphdr; unsigned short iphdrlen; iphdr=(ipheader*)buf; iphdrlen=iphdr->headlen*4; /IP报头的长度 icmphdr=(icmpheader *)(buf+iphdrlen); /跳过IP头 /数据包太短 丢弃 if(bytes&l
20、t;iphdrlen+icmp_min) return; /不是回送请求(ping应答),丢弃 if(icmphdr->type!=icmp_echo_reply) return; /ID不相符,丢弃if(icmphdr->id!=(USHORT)getcurrentthreadid() return; /输出正在使用的IP地址 cout<<"活动主机"<<inet_ntoa(from->sin_addr)<<endl;源代码:#pragma pack(4)#pragma comment(lib,"Ws2_32
21、.lib")#define win32_LEAN_AND_MEAN#include <winsock2.h>#include <stdio.h>#include <iostream.h>#include <stdlib.h>#include <sys/timeb.h>#include <time.h>/THE IP HEADERtypedef struct iphdr unsigned int headlen:4; /ip头长度 unsigned int wersion:4; /ip版本号 unsigned ch
22、ar tos; /服务类型unsigned short totallen; /ip包总长度unsigned short id; /ip号unsigned short flag; /标记unsigned char ttl; /生存时间unsigned char prot; /协议(UDP TCP)unsigned short checksum; /校验和unsigned int sourceip; /源ipunsigned int destip; /目的ipIpHeader;/ICMP HEADERtypedef struct icmphdr BYTE type; /icmp类型码,回送请求的类
23、型码为8 BYTE code; /子类型码,保存与特定ICMP报文类型相关的/节信息 USHORT checksum; /校验和 USHORT id; /ICMP报文id号 USHORT seq; /ICMP数据报的序列号Icmpheader;#define ICMP_ECHO 8 /请求回送#define ICMP_ECHO_REPLY 0 /请求回应#define ICMP_MIN 8 /ICMP包头长度(最小ICMP包长度)#define STATUS_FAILED 0xFFFF /错误码#define DEF_PACKET_SIZE 32 /缺省数据报长度#define MAX_PAC
24、KET 1024 /最大数据报长度#define MAX_PING_PACKET_SIZE (MAX_PACKET + sizeof(IpHeader) /最大接受数据报长度void fill_icmp_date(char * ,int); /填充ICMP包USHORT checksum(USHORT *,int); /校验和函数void decode_resp(char*,int,struct sockaddr_in *); /找到此数据报IP地址DWORD WINAPI FindIp(LPVOID pipaddrtemp); /线程调用子函数#include "scanhost.
25、h"WSADATA wsadata;SOCKET sockraw;struct sockaddr_in dest, from,end;int fromlen = sizeof(from);char * recvbuf = new charMAX_PING_PACKET_SIZE;unsigned int addr = 0;long threadnumcounter = 0, threadnumlimit = 20;long *aa = &threadnumcounter;void main(int argc, char *argv)if(argc != 3)cout<&
26、lt;"输入格式错误:scanhost start_ip end_ip"<<endl;getchar();if(WSAStartup(MAKEWORD(2,1), &wsadata) != 0)cout<<"WSAStartup failed:"<<GetLastError()<<endl;ExitProcess(STATUS_FAILED);/创建原始套接字sockraw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_
27、OVERLAPPED);if(sockraw = INVALID_SOCKET)cout<<"WSASocket() failed:"<<WSAGetLastError()<<endl;ExitProcess(STATUS_FAILED); /设置读取延时int timeout = 1000;int bread = setsockopt(sockraw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout);if(bread = SOCKET_ERROR)cout<
28、;<"fail to set recv timeout:"<<WSAGetLastError()<<endl;ExitProcess(STATUS_FAILED);timeout = 1000;bread = setsockopt(sockraw, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout);if(bread = SOCKET_ERROR)cout<<"failed to set send timeout:"<<WSAGe
29、tLastError()<<endl;ExitProcess(STATUS_FAILED); memset(&dest, 0, sizeof(dest);unsigned long startip, endip;dest.sin_family = AF_INET; dest.sin_addr.s_addr = inet_addr(argv1);startip = inet_addr(argv1);end.sin_family = AF_INET;end.sin_addr.s_addr = inet_addr(argv2);endip = inet_addr(argv2);H
30、ANDLE hthread;while(htonl(startip) <= htonl(endip)if(threadnumcounter > threadnumlimit)Sleep(5000);continue;DWORD Threadid;sockaddr_in * pipaddrtemp = new(sockaddr_in);if(!pipaddrtemp)cout<<"memory alloc failed"<<endl;return;*pipaddrtemp = dest;/创建新线程clock_t start;start =
31、 clock();hthread = CreateThread(NULL, NULL, FindIp, (LPVOID)pipaddrtemp, NULL, &Threadid);long i = 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!
32、=0)Sleep(2000);return;void fill_icmp_data(char * icmp_data, int datasize)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
33、 - sizeof(Icmpheader);void decode_resp(char *buf, int bytes, struct sockaddr_in *from)IpHeader *iphdr;Icmpheader *icmphdr;unsigned short iphdrlen;iphdr = (IpHeader *)buf;iphdrlen = iphdr->headlen * 4;icmphdr = (Icmpheader *)(buf + iphdrlen);/数据包太短 丢弃if(bytes < iphdrlen + ICMP_MIN) return;if(ic
34、mphdr->type != ICMP_ECHO_REPLY) return;if(icmphdr->id != (USHORT)GetCurrentThreadId() return;cout<<"活动主机"<<inet_ntoa(from->sin_addr)<<endl;USHORT checksum(USHORT *buffer, int size)unsigned long cksum = 0; while (size > 1)cksum += *buffer+;size -= sizeof(USHORT
35、);if(size)cksum += *(UCHAR*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (USHORT)(cksum);DWORD WINAPI FindIp(LPVOID pipaddrtemp)InterlockedIncrement(aa); char icmp_dataMAX_PACKET; memset(icmp_data, 0, MAX_PACKET); int datasize = DEF_PACKET_SIZE; da
36、tasize += sizeof(Icmpheader); 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); int bwrote = sendto(sockraw, icmp_data, datasize, 0, (struct so
37、ckaddr* )pipaddrtemp, sizeof(dest); int n = 0; if (bwrote = SOCKET_ERROR) if(WSAGetLastError() = WSAETIMEDOUT) cout<<"timed out"<<endl; cout<<"sendto failed: "<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); n = 1; if(bwrote < datasize) cout
38、<<"worte "<<bwrote<<" bytes"<<endl; ExitProcess(STATUS_FAILED); n = 1; int bread = recvfrom(sockraw, recvbuf, MAX_PING_PACKET_SIZE, 0, (struct sockaddr* ) &from, &fromlen); if(bread = SOCKET_ERROR) if(WSAGetLastError() = WSAETIMEDOUT) cout<<"time out"<<endl; cout<<"recvform failed:"<<WSAGetLastError()<<endl; ExitProcess(STATUS_FAILED); n = 1; if(n = 0) decode_resp(recvb
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB 14249-2026电子衡器安全要求
- 工程造价 考核制度
- 采用连带责任考核制度
- 培训班班主任考核制度
- 消保考核制度实施细则
- 打印中心管理考核制度
- 灌装车间线长考核制度
- 电线电缆绩效考核制度
- 绍兴演艺集团考核制度
- 案场置业顾问考核制度
- 近五年宁夏中考物理真题及答案2024
- 医用导管标识规范
- 七年级下人教版英语单词表
- 课题申报参考:《大学语文》教学改革与实践
- 译林版初中教材词汇表(默写版)
- 洗罐设备项目可行性研究报告
- 运用PDCA循环降低初次剖宫产率
- 临床康复专科护士主导神经重症患者早期渐进式离床活动实践应用
- 2024年全新PE工程师培训教材发布
- 老年代步车免责合同协议书范文
- 职业技术学校安全保卫管理专业人才培养方案
评论
0/150
提交评论