计算机网络实验报告资料.docx
- 文档编号:11465188
- 上传时间:2023-03-01
- 格式:DOCX
- 页数:18
- 大小:213.40KB
计算机网络实验报告资料.docx
《计算机网络实验报告资料.docx》由会员分享,可在线阅读,更多相关《计算机网络实验报告资料.docx(18页珍藏版)》请在冰豆网上搜索。
计算机网络实验报告资料
课程设计
课程名称
题目名称
学生学院
专业班级
学号
学生姓名
指导教师
2015年12月28日
一、课程设计目的与意义
二、课程设计的要求
三、设计说明
3.1、设计思路
3.2、设计方案
3.3、运行环境
3.4、设计重点
四、详细设计
4.1、主程序流程图
4.2、校验和函数、释放资源函数流程图
4.3、ICMP报首部函数流程图
五、程序的结果与分析
六、课程设计心得体会
附录一:
参考文献
附录二:
程序源代码
一、课程设计的目的与意义
利用ICMP数据包、C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间的连通情况。
通过本程序的训练,熟悉ICMP报文结构,对ICMP有更深的理解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。
二、课程设计的要求
1.已知参数:
目的节点IP地址或主机名
2.设计要求:
通过原始套接字编程,实现Ping的基本功能
2.1初始化WindowsSockets网络环境;
2.2解析命令行参数,构造目的端socket地址;
2.3定义IP、ICMP报文;
2.4接收ICMP差错报文并进行解析。
三、设计说明
1.设计思路
由于Ping程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。
为了实现直接对IP和ICMP包进行操作,实验中使用RAW模式的socket编程。
首先定义IP数据报首部,在IP数据报的基础上定义ICMP数据报首部,并初始化一些全局变量。
接着自定义填充ICMP数据报字段函数FillICMPData()、校验和函数checksum()、解读ICMP报首部函数DecodeICMPHeader()、释放资源函Cleanup()。
最后主函数通过调用这些函数来实现Ping命令功能。
2.设计方案
IP头与ICMP头的设置分别参照RFC791及RFC792的标准,包含所有必要信息。
主程序设置main()函数,主函数用库函数实现套接字编程用于数据包发送及接收,其中,数据包发送调用sendto(),数据包接收调用recvfrom(),由于发送数据包时可能会遇到阻塞或者目标主机不通,造成超时,因此需要在发送数据包后调用一个函数判断是否超时,此处调用库函数setsockopt()来实现超时判断;其次,校验和函数采用移位方法进行计算。
3.系统运行环境:
VC++6.0,Window7操作系统平台
4.设计中的重点
首先遇到的问题就是套接字文件的问题。
套接字所需要的文件有头文件Winsocket2.h、库文件WS2_32.LIB、动态库W32_32.DLL。
创建套接字的时候参数的以及在创建套接字之前必须首先使用WSAStartup函数、在使用完套接字之后要释放内存资源,关闭套接字这些问题都是以前未接触过的。
所以在写程序的时候需要查阅大量的资料,弄懂这些问题。
其次,在套接字问题解决之后,遇到的难题,也是比较重要的问题就是如何实现ICMP报文的发送和接受,以及怎样判断发送、接收超时或者找不到目的主机。
最后在程序调试的时候总是出现这样或那样的错误,比如头文件错误、动态库无法导入、编辑器环境不匹配等。
四、详细设计
1、本程序主要是通过main()函数调用自定义函数以及其本身的一些功能,例如:
打开socket动态库、设置接收和发送超时值、域名地址解析、分配内存、创建及初始化ICMP报文、发送ICMP请求报文、接收ICMP应答报文以及解读应答报文和输出Ping结果。
程序流程图如下:
否
是
是
否
否
2、校验和函数、释放资源函数流程图如下:
是
否是否
是
否
3、ICMP报首部函数流程图如下:
五、程序的结构与分析
运行结果截图如下:
结果分析:
1、Requesttimedout(请求超时)
(1)对方已关机,或者网络上根本没有这个地址:
比如在上图中Ping14.150.213.222
(2)对方与自己不在同一网段内,通过路由也无法找到对方,但有时对方确实是存在的,当然不存在也是返回超时的信息。
(3)对方确实存在,但设置了ICMP数据包过滤(比如防火墙设置)。
2、DestinationhostUnreachable(目标不可达)
(1)错误设置IP地址
六、课程设计心得体会
本次课程设计较好地实现了要求做到的功能,但同时也遇到不少的困难和挑战。
通过这次设计,不但加深了对Socket的原始套接字编程的理解,经过实现Ping程序,熟悉了IP、ICMP等,掌握TCP/IP网络协议的基本实现方法。
也熟悉了Window网络编程的技术。
能熟悉地使用套接字进行网络通信。
熟悉了数据通信的网络技术,同时学会了跟同学合作交流完成项目的讨论方法和解决问题的能力。
学会如果通过讨论、交流、找资料来独立解决所遇到的问题和不懂。
更多地锻炼了独立解决问题的能力。
在编写过程中,一些基本的常见的函数不会应用,这使我们小组都发现自己知识的匮乏,在以后的学习过程中得要好好的努力,多阅读一些复杂的程序,了解一个基本的函数,算法和精良的编程思想,更要多动手写一些有一定难度的程序,我们不应该害怕写程序出错,应该大胆地写出自己的想法,出现错误去解决错误就能找出自己知识的漏洞和模糊点。
我们还可以通过阅读别人错误的程序,试着帮别人查找错误,这样证书技能头脑中的规则还能发现一些初学者一番的错误,使自己少走弯路。
附录一:
参考文献
【1】计算机网络谢希仁编著电子工业出版社
【2】C程序设计谭浩强编著北京清华大学出版社
附录二:
程序源代码及部分注释
#include"stdafx.h"
#pragmacomment(lib,"ws2_32.lib")
#include
#include
#include
#include
#include
#include
typedefstructiphdr
{
unsignedinth_len:
4;//头长度
unsignedintversion:
4;//IP版本
unsignedcharservice;//服务类型
unsignedshorttotal_len;//包的总长度
unsignedshortident;//包标示身份
unsignedshortfrag_and_flags;//标志
unsignedcharttl;//包生命周期
unsignedcharproto;//协议类型
unsignedshortchecksum;//IP校验
unsignedintsourceIP;//源IP
unsignedintdestIP;//目标IP
}IpHeader;
#defineICMP_ECHO8//ICMP报文类型,回显请求
#defineICMP_ECHOREPLY0//ICMP报文类型,回显响应应答
#defineICMP_MIN8//最小的ICMP数据报大小
typedefstructicmphdr
{
BYTEi_type;//ICMP报文类型
BYTEi_code;//该类型中的代码号
USHORTi_cksum;//校验和
USHORTi_id;//惟一的标识符
USHORTi_seq;//序列号
ULONGtimestamp;//时间戳
}IcmpHeader;
#defineDEF_PACKET_SIZE32//默认数据报大小
#defineMAX_PACKET1024//最大的ICMP数据报大小
#defineMAX_IP_HDR_SIZE60//最大IP头长度
//初始化全局变量
intdatasize=DEF_PACKET_SIZE;
char*icmp_data=NULL;
char*recvbuf=NULL;
SOCKETm_hSocket=INVALID_SOCKET;
char*lpdest=NULL;
//填充ICMP数据报字段函数
voidFillICMPData(char*icmp_data,intdatasize)
{
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();//GetCurrentProcessId()获取当前进程的标示符(PID)
icmp_hdr->i_cksum=0;
icmp_hdr->i_seq=0;
datapart=icmp_data+sizeof(IcmpHeader);
}
//校验和函数
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);
}
//解读ICMP报首部函数
voidDecodeICMPHeader(char*buf,intbytes,SOCKADDR_IN*from)
{
IpHeader*iphdr=NULL;
IcmpHeader*icmphdr=NULL;
unsignedshortiphdrlen;
DWORDtick;
staticinticmpcount=0;
iphdr=(IpHeader*)buf;//从buf中获取IP数据包头指针
iphdrlen=iphdr->h_len*4;
tick=GetTickCount();
if(bytes { printf("Toofewbytesfrom%s\r\n",inet_ntoa(from->sin_addr)); } icmphdr=(IcmpHeader*)(buf+iphdrlen);//定位ICMP包头起始位置 if(icmphdr->i_type! =ICMP_ECHOREPLY) { printf("nonechotype%dreceived\r\n",icmphdr->i_type); } if(icmphdr->i_id! =(USHORT)GetCurrentProcessId()) { printf("其他程序的回应报文! \t错误代码%d\n",WSAGetLastError()); } inttick0; tick0=tick-icmphdr->timestamp; if(tick0<1) printf("Replyfrom%s: bytes=%dtime<1msicmp_seq=%d\n",inet_ntoa(from->sin_addr),bytes,icmphdr->i_seq); else printf("Replyfrom%s: bytes=%dtime=%dmsicmp_seq=%d\n",inet_ntoa(from->sin_addr),bytes,tick0,icmphdr->i_seq); } //释放资源函数 voidCleanup() { if(m_hSocket! =INVALID_SOCKET) closesocket(m_hSocket); HeapFree(GetProcessHeap(),0,recvbuf); HeapFree(GetProcessHeap(),0,icmp_data); WSACleanup(); } //主函数 voidmain() { WSADATAwsaData; chara[100]; printf("ping"); gets(a); lpdest=a; SOCKADDR_INm_addrDest;//结构体 SOCKADDR_INm_addrFrom; inttimeout=1000; USHORTseq_no=0; if(WSAStartup(MAKEWORD(2,2),&wsaData)! =0) { printf("Sorry,youcannotloadsocketdll! "); } m_hSocket=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);//创建原始套接字,该套接字用于ICMP协议 if(m_hSocket==INVALID_SOCKET)//如果套接字创建不成功 { printf("socket创建失败! "); } intbread=setsockopt(m_hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));//设置接收的超时值 if(bread==SOCKET_ERROR) { 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地址族 if((m_addrDest.sin_addr.s_addr=inet_addr(lpdest))==INADDR_NONE)//地址转化 { structhostent*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;//将获取到的地址族值赋给目的地地址中的相应字段 } else { printf("不能找到名为%s的主机\t错误代码%d\n",lpdest,WSAGetLastError());//获取不成功 exit(0); } } printf("Pinging%swith64bytesofdata: \n\n",inet_ntoa(m_addrDest.sin_addr));//inet_ntoa()将网络地址转换成“.”点隔的字符串格式 datasize+=sizeof(IcmpHeader);//数据报文大小需要包含ICMP报头 //根据默认堆句柄,从堆中分配MAX_PACKET内存块,新分配内存的内容将被初始化为0 icmp_data=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET); recvbuf=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET); if(! icmp_data)//如果分配内存不成功 { printf("堆分配错误! "); } memset(icmp_data,0,MAX_PACKET);//将已开辟内存空间 icmp_data 的首 MAX_PACKET 个字节的值设为值 0。 FillICMPData(icmp_data,datasize);//创建ICMP报文, //开始发送或接受ICMP包 intnCount=0; while (1) { intbwrote; if(strstr(a,"-t")==NULL&&nCount++==4)//判断a字符数组中是否包含-t参数并且已发ICMP包4次 break;//超过指定的记录条数则退出 ((IcmpHeader*)icmp_data)->i_cksum=0;//计算校验和前要把校验和字段设置为0 ((IcmpHeader*)icmp_data)->timestamp=GetTickCount();//获取操作系统启动到现在所经过的毫秒数,设置时间戳 ((IcmpHeader*)icmp_data)->i_seq=seq_no++;//设置序列号 ((IcmpHeader*)icmp_data)->i_cksum=checksum((USHORT*)icmp_data,datasize);//计算校验和 bwrote=sendto(m_hSocket,icmp_data,datasize,0,(structsockaddr*)&m_addrDest,sizeof(m_addrDest));//开始发送ICMP请求 if(bwrote==SOCKET_ERROR)//如果发送不成功 { if(WSAGetLastError()==WSAETIMEDOUT)//如果是由于超时不成功 { printf("Requresttimedout! \r\n"); continue; } printf("目标不可达! \t错误代码%d\n",WSAGetLastError());//其他发送不成功原因 continue; } if(bwrote { printf("Wrote%dbytes\r\n",bwrote); } intfromlen=sizeof(m_addrFrom);//开始接收ICMP应答 bread=recvfrom(m_hSocket,recvbuf,MAX_PACKET,0,(structsockaddr*)&m_addrFrom,&fromlen);//recvfrom()用来接收远程主机经指定的socket传来的数据,并把数据传到由参数recvbuf指向的内存空间 if(bread==SOCKET_ERROR)//如果接收不成功 { if(WSAGetLastError()==WSAETIMEDOUT)//如果是由于超时不成功 { printf("Requresttimedout! \r\n"); continue; } printf("接收数据函数调用错误! \t错误代码%d\n",WSAGetLastError());//其他接收不成功原因 exit(0); } DecodeICMPHeader(recvbuf,bread,&m_addrFrom);//解读接收到的ICMP数据报 Sleep(800); } Cleanup(); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机网络 实验 报告 资料