计算机网络基础课程设计-Ping程序的实现_第1页
计算机网络基础课程设计-Ping程序的实现_第2页
计算机网络基础课程设计-Ping程序的实现_第3页
计算机网络基础课程设计-Ping程序的实现_第4页
计算机网络基础课程设计-Ping程序的实现_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、计算机网络工程课程设计报告题 目: Ping程序的实现 学生姓名: 学 号: 专业班级: 计科专业10102班 同组姓名: 指导教师: 设计时间: 2013年下学期第16周 指导老师意见:评定成绩: 签名: 日期: 年 月 日 目录 TOC o 1-3 h z u HYPERLINK l _Toc359456695 一、课程设计的目的和意义 PAGEREF _Toc359456695 h 2 HYPERLINK l _Toc359456696 二、课程设计的内容和要求 PAGEREF _Toc359456696 h 2 HYPERLINK l _Toc359456697 1.内容: PAGER

2、EF _Toc359456697 h 2 HYPERLINK l _Toc359456698 2.要求: PAGEREF _Toc359456698 h 2 HYPERLINK l _Toc359456699 三、课程设计的相关技术 PAGEREF _Toc359456699 h 2 HYPERLINK l _Toc359456700 四、课程设计过程 PAGEREF _Toc359456700 h 2 HYPERLINK l _Toc359456701 1.Ping主模块 PAGEREF _Toc359456701 h 2 HYPERLINK l _Toc359456702 2.功能控制模块

3、 PAGEREF _Toc359456702 h 4 HYPERLINK l _Toc359456703 3.数据报解析模块 PAGEREF _Toc359456703 h 5 HYPERLINK l _Toc359456704 五、课程设计小结 PAGEREF _Toc359456704 h 6 HYPERLINK l _Toc359456705 六、参考文献 PAGEREF _Toc359456705 h 7 HYPERLINK l _Toc359456706 七、附 录(程序清单) PAGEREF _Toc359456706 h 7 HYPERLINK l _Toc359456707 八

4、、心得体会 PAGEREF _Toc359456707 h 11一、课程设计的目的和意义利用ICMP数据包、C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试个主机到只一个主机之间的连通情况。通过本程序的训练,使学生熟悉ICMP报文结构,使学生对ICMP有更深的理解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。二、课程设计的内容和要求1.内容:用C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试个主机到只一个主机之间的连通情况。2.要求: 独立完成程序的设计、编码和调试。系统利用C

5、语言实现,程序调试环境为Turbo C或VC;按照课程设计规范书写课程设计报告。采用VC环境进行调试运行。三、课程设计的相关技术由于Ping程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。为了实现直接对IP和ICMP包进行操作,实验中使用RAW模式的socket编程。首先定义IP数据报首部,在IP数据报的基础上定义ICMP数据报首部,并初始化一些全局变量。接着自定义填充ICMP数据报字段函数FillICMPData()、校验和函数checksum()、解读ICMP报首部函数DecodeICMPHeader()、释放资源函Cleanup()。最后主函数通过调用这些函数

6、来实现Ping命令功能。IP头与ICMP头的设置分别参照RFC791及RFC792的标准,包含所有必要信息。主程序设置main()函数,主函数用库函数实现套接字编程用于数据包发送及接收,其中,数据包发送调用sendto(),数据包接收调用recvfrom( ),由于发送数据包时可能会遇到阻塞或者目标主机不通,造成超时,因此需要在发送数据包后调用一个函数判断是否超时,此处调用库函数setsockopt()来实现超时判断;其次,校验和函数采用移位方法进行计算。套接字所需要的文件有头文件Winsocket2.h、库文件WS2_32.LIB、动态库W32_32.DLL。创建套接字的时候参数的以及在创建

7、套接字之前必须首先使用WSAStartup函数。四、课程设计过程1.Ping主模块Ping()函数是本程序的核心部分,它基本是调用其他模块的函数来实现最终功能,其主要布骤包括:定义及初始化各个全局变量、打开socket动态库、设置接收和发送超时值、域名地址解析、分配内存、创建及初始化ICMP报文、发送ICMP请求报文、接收ICMP 应答报文以及解读应答报文和输出Ping结果,最后释放占用的资源其流程如下页图2.1所示。注释:该模块并非只有处理还包括判断及输出判断结果的含义;程序没运行一次就只能输出四行结果(前提是输入的地址有效),欲再次PING其他地址必须要重新启动程序。输入时不能输入目标主机

8、名,不然ping结果为TIMEOUT;开始定义及初始化各个全局变量判断WSAStartup函数是否调用成功输出调用失败否创建套接字以及设置socket接收超时,发送超时选项;是输入PING的IP地址解析输入内容,设置PING参数创建及填充ICMP数据报文判断是否已发送四次Break;发送,接收以及解析数据包输出PIING结果是结束清除残余否2.功能控制模块功能控制模块主要是为其他模块提供可调用的函数,该模块主要包括参数获取功能、计算ICMP数据报文检验和、清除SOCKET,ICMP包数据以及接受缓冲区、占用资源释放功能和显示用尸帮助功能。该模块一共包含三个函数来实现。,流程如图2.2所示。Ch

9、ecksum开始定义初始化cksum (size 1)确定cksum及size大小是if (size)计算校验cksum,获得结果cksum += *(UCHAR*)buffer;否结束Cleanup开始if (m_hSocket != INVALID_SOCKET)关闭套接字释放占用资源清除ICMP包数据以及接受缓冲区FWSACleanup();结束图2.2 功能控制模块注释:a.illICMPData是由一系列的初始化的语句在流程图中不再画出;b.Cleanup()函数中的WSACleanup(),HeapFree(),closesocket()都是一些库函数。checksum()校验和函

10、数是冗余校验的一种形式。 它是通过错误检测方法,对经过空间(如通信)或者时间(如计算机存储)传送的数据的完整性进行检查的一种简单方法。3.数据报解析模块数据报解析模块提供了解读IP选项和解读IcMP报文的功能。从本机收到目的主机返回的1cMP回显应答报文,就开始逐个地解读IcMP报文,如果需要记录路由的情况下,IcMP解析函数将调用IP选项解读函数来实现IP路由的输出(但本程序没有此功能。该模块主要由DecodeICMPHeader一个函数来实现,而中间也会调用其它模块的相应函数。其流程图如图2.3:注释:a.判断是否为我们所要的数据报回应之前,还有一些判断回应多少内容的语句未呈现出;b.函数

11、GetTickCount()是用来记录此时我机所处的现在时间(毫秒级);DecodeICMPHeader开始定义相关变量以及初始化;tick = GetTickCount();为我们所要的回应报文;是输出不是我们所要;tick0icmpcount=tick - icmphdr-timestamp;判断时间是否小于1msprintf(Reply from %s: dytes=%d timesin_addr), bytes, icmphdr-i_seq );printf(Reply from %s: dytes=%d time=%d icmp_seq = %dn,inet_ntoa(from-si

12、n_addr), bytes,tick0icmpcount, icmphdr-i_seq);是是icmpcount+;结束结束否图2.3 数据报解析模块五、课程设计小结1.运行操作结果:在vc里运行之后界面:2.输入本机ip地址:3.输入网上ip看结果:4. 但是当网络连不通时,就会出现下图结果六、参考文献【1】Visual C+网络通信编程实用案例精选(第二版)曹衍龙 刘海英 编著;【2】Windows网络编程技术 (美);七、附 录(程序清单)#pragma comment(lib,ws2_32.lib)#include /创建套接字头文件#include #include /标准输入输出

13、函数#include /实用程序库函数#include typedef struct iphdr unsigned int h_len:4; / 头长度unsigned int version:4; / IP版本 unsigned char service; / 服务类型 unsigned short total_len; / 包的总长度 unsigned short ident; / 包标示身份 unsigned short frag_and_flags; / 标志 unsigned char ttl; / 包生命周期 unsigned char proto; / 协议类型 unsigned

14、 short checksum; / IP 校验 unsigned int sourceIP; /源IP unsigned int destIP; /目标IP IpHeader;#define ICMP_ECHO 8 /ICMP报文类型,回显请求 #define ICMP_ECHOREPLY 0 /ICMP报文类型,回显应答#define ICMP_MIN 8 /最小的ICMP数据报大小 typedef struct icmphdr BYTE i_type; /ICMP报文类型 BYTE i_code; /该类型中的代码号 USHORT i_cksum; /校验和 USHORT i_id; /

15、惟一的标识符 USHORT i_seq; /序列号 ULONG timestamp; /时间戳 IcmpHeader;#define DEF_PACKET_SIZE 32 /默认数据报大小#define MAX_PACKET 1024 / 最大的ICMP数据报大小 #define MAX_IP_HDR_SIZE 60 / 最大IP头长度 /初始化全局变量 int datasize=DEF_PACKET_SIZE; char *icmp_data=NULL;char *recvbuf=NULL; SOCKET m_hSocket= INVALID_SOCKET; char *lpdest=NUL

16、L;/填充ICMP数据报字段函数void FillICMPData(char *icmp_data, int datasize) IcmpHeader *icmp_hdr = NULL; char*datapart = NULL; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr-i_type = ICMP_ECHO; icmp_hdr-i_code = 0; icmp_hdr-i_id = (USHORT)GetCurrentProcessId(); icmp_hdr-i_cksum = 0; icmp_hdr-i_seq = 0; datapart =

17、 icmp_data + sizeof(IcmpHeader);/校验和函数USHORT checksum(USHORT *buffer, int size) unsigned long cksum=0; while (size 1) cksum += *buffer+; size -= sizeof(USHORT); if (size) cksum += *(UCHAR*)buffer; cksum = (cksum 16) + (cksum & 0 xffff); cksum += (cksum 16);return (USHORT)(cksum);/解读ICMP报首部函数void Dec

18、odeICMPHeader(char *buf, int bytes, SOCKADDR_IN *from) IpHeader*iphdr = NULL; IcmpHeader*icmphdr = NULL; unsigned short iphdrlen; DWORD tick; static int icmpcount = 0; iphdr = (IpHeader *)buf; iphdrlen = iphdr-h_len * 4; tick = GetTickCount(); if (bytes sin_addr); icmphdr = (IcmpHeader*)(buf + iphdr

19、len); if (icmphdr-i_type != ICMP_ECHOREPLY) printf(nonecho type %d received rn, icmphdr-i_type); if (icmphdr-i_id != (USHORT)GetCurrentProcessId() printf(其他程序的回应报文! t错误代码 %dn, WSAGetLastError(); DWORD tick04; tick0icmpcount=tick - icmphdr-timestamp;if(tick0icmpcount1)printf(Replyfrom %s: bytes=%d ti

20、mesin_addr), bytes, icmphdr-i_seq );else printf(Reply from %s: bytes=%d time=%dms icmp_seq = %dn,inet_ntoa(from-sin_addr), bytes,tick0icmpcount, icmphdr-i_seq); icmpcount+;/释放资源函数void Cleanup() if (m_hSocket != INVALID_SOCKET) closesocket(m_hSocket); HeapFree(GetProcessHeap(), 0, recvbuf); HeapFree(

21、GetProcessHeap(), 0, icmp_data); WSACleanup();/主函数void main()WSADATA wsaData; char a100; printf(ping );scanf(%s,a); lpdest=a; SOCKADDR_IN m_addrDest;/结构体 SOCKADDR_IN m_addrFrom; int timeout=1000; USHORT seq_no=0;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) printf(Sorry, you cannot load socket dll!

22、); m_hSocket = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED);/创建原始套接字,该套接字用于ICMP协议 if (m_hSocket = INVALID_SOCKET) /如果套接字创建不成功 printf(socket 创建失败!); int bread = setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout);/设置接收的超时值 if(bread = SOCKET_ERRO

23、R) printf(设置socket接收超时选项错误!); timeout = 1000; bread = setsockopt(m_hSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout);/设置发送的超时值 if (bread = SOCKET_ERROR) printf(设置socket发送超时选项错误!); memset(&m_addrDest, 0, sizeof(m_addrDest);/ 用0初始化目的地地址 m_addrDest.sin_family = AF_INET;/设置地址族,这里表示使用IP地

24、址族 if (m_addrDest.sin_addr.s_addr = inet_addr(lpdest) = INADDR_NONE)/地址转化 struct hostent *hp = NULL; if (hp = gethostbyname(lpdest) != NULL) /名字解析,根据主机名获取IP地址 memcpy(&(m_addrDest.sin_addr), hp-h_addr, hp-h_length);/将获取到的IP值赋给目的地地址中的相应字段m_addrDest.sin_family = hp-h_addrtype; /将获取到的地址族值赋给目的地地址中的相应字段 e

25、lse printf(不能找到名为 %s 的主机t错误代码 %dn,lpdest, exit(0); printf(Pinging %s with 64 bytes of data: nn, inet_ntoa(m_addrDest.sin_addr); datasize += sizeof(IcmpHeader); /数据报文大小需要包含ICMP报头/根据默认堆句柄,从堆中分配MAX_PACKET内存块,新分配内存的内容将被初始化为0 icmp_data=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET); recvb

26、uf =(char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,MAX_PACKET); if (!icmp_data) /如果分配内存不成功 printf(堆分配错误!); memset(icmp_data,0,MAX_PACKET);/创建ICMP报文 FillICMPData(icmp_data,datasize); / 开始发送或接受ICMP包int nCount=0; while(1) int bwrote; if(nCount+ = 4) break;/超过指定的记录条数则退出 (IcmpHeader*)icmp_data)-i_cksum = 0;/计算校验和前要把校验和字段设置为0 (IcmpHeader*)icmp_data)-timestamp = GetTickCount();/获取操作系统启动到现在所经过的毫秒数,设置时间戳 (IcmpHeader*)icmp_data)-i_seq = seq_no+;/设置序列号 (IcmpHe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论