

免费预览已结束,剩余27页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
计算机网络课程设计 题 目 ping程序与echo程序的设计与实现 系 部 商学系 专 业 信息管理与信息系统 班 级 信息n122 学 号 学生姓名 指导教师 编写日期 2014.12.25 目录1.目的22.要求23.知识34.分析35.代码96.结果307.心得301. 目的通过设计ping程序,讲解ping程序的实现原理,并初步讲解了c语言网络编程技术。本章涉及很多网络编程函数和编程技巧。包括库文件的导入;winsock的初始化、注销;socket的创建、关闭;设置socket选项;根据主机名获取ip地址; 从堆中分配一定数量的空间、释放从堆中分配的空间;获取当前进程id号;数据报的发送;数据报的接等。echo程序的功能是客户端向服务器发送一个字符串,服务器不做任何处理,直接把字符串返还给客服端,echo程序是最为基本的客户端/服务器程序。a、 通过echo程序是学生掌握网络编程的基本知识和基本技能;b、 通过跟踪运行java包,使学生了解网络编程实现的细节。课程设计内容:本实验要求实现echo程序,具有内容及要求如下:a、 分析echo程序的功能,其功能包括:客户端输入一个字符串;服务器端接收到这个字符串后,直接把这些字符串发送给客户端;客户端在接收到这个字符串后把字符串现实出来。b、 设计实现echo程序,包括客户端和服务器程序。c、 跟踪运行java包。2. 要求(1)实现ping功能。程序能实现基本的ping操作,发送icmp回显请求报文,接收显应答报文。(2)能记录路由。程序提供了“-r”选项,用以记录从源主机到目的主机的路由。(3)能输出指定条数的记录。程序提供了“-n”选项,用以输出指定条数的记录。(4)能按照指定大小输出每条记录。程序提供了“datasize”选项,用以指定输出的数据报的大小。(5)能输出用户帮助。程序提供了用户帮助,显示程序提供的选项以及选项格式等。echo程序的实现主要是利用java网络程序包中的服务器套接字(serverssocket)和客户端套接字(socket)来实现,思路如下:根据制定的端口创建服务器套接字,并阻塞客户的连接;根据echoservice所以主机名和侦听端口创建客户端套接字;向客户端套接字输出流中写入一个字符串;服务器套接字接收到连接请求,从服务器套接字输入流中读取该字符串;服务器套接字不做任何修改,直接把该字符串写入服务器套接字输出流中;客户端套接字从输入流中接收到 该字符串,直接打印到终端。3. 知识ping命令是使用频率极高的一个网络测试命令,用以测试从一个主机到另一个主机间的网络上否可达。windows自带的ping命令具有强大的功能,它有很多选项用于实现不同的测试目的。本章模仿windows的ping命令,用c语言实现了一个简单的命令。本章着重讲述ping命令的实现原理和c语言的网络编程方法。读者可以在本章的基础上,对本章实现的ping命令进行扩展,开发出功能更强大、更完善的ping命令,并进一步掌握网络编程的方法。4. 分析1. 功能模块图本系统共有 4 个模块,分别是初始化模块、功能控制模块、数据控制模块、数据报解读模块和ping测试模块,如图9.1所示。各模块功能描述如下。ping程序设计初始化模块数ping命令是使用频率极高的一个网络测试命令,用以测试从一个主机到另一个主机间的网络上否可达。windows自带的ping命令具有强大的功能,它有很多选项用于实现不同的测试目的。本章模仿windows的ping命令,用c语言实现了一个简单的命令。本章着重讲述ping命令的实现原理和c语言的网络编程方法。读者可以在本章的基础上,对本章实现的ping命令进行扩展,开发出功能更强大、更完善的ping命令,并进一步掌握网络编程的方法据报解读模块功能控制模块ping测试模块图4.1系统模块图(1) 初始化模块。改模块用于初始化各个全局变量,为全局变量赋初始值;初始化,加载库。(2)功能控制模块。改模块是被其它模块调用,其功能包括获取参数、计算校验和填充数据报文、释放占用资源和显示用户帮助。(3)数据报解读模块。改模块用于解读接收到的报文和选项。(4)测试模块。改模块是本程序的核心模块,调用其他模块实现其功能,主要是实现的功能。 2系统流程图系统执行的流程图9.2所示。程序首先调用iniping()函数初始化各全局变量,然后getargments()函数获取用户输入的参数,检查用户输入的参数,如果参数不正确或者没有输入参数,则显示用户帮助信息(user help ),并结束程序;如果参数正确,则对指定目的地执行ping命令,如果ping通,则显示ping结果并释放占用资源,如果没有ping通,则报告错误信息,并释放占用资源。开始初始化个变量获取参数信息输入参数是否正确?ping目的地ping成功?输出ping结果释放占用资源结束输出错误信息显示帮助信息图4.2 系统流程图3.参数获取(getargments()函数)流程图获取的参数包括“-r”(记录路由)、“-n”(记录条数程序,任意的整数)和datasize(数据报大小)。程序首先判断每一个参数的第一字符,如果第一个字符是“-”(短横线),则认为是“-r”或者“-n”中的一个,然后作进一步判断。如果该参数的第二个字符是数字,则判断该参数为记录的条数,如果该参数的第二个字符是“r”,则判断该参数为“-r”, 用于记录路由;如果参数的第一个字符是数字,则认为 参数是ip地址;或者datasize,然后作进一步的判断。如果该参数中不存在非数字的字符, 则判断该参数为datasize;如果存在非数 字的字符,则判断该参数为ip地址;其他情况则判断为主机名。参数获取的流程如图所示:开始argc=1?检查第一i个参数的第一个字符是“-”?检查第一i个参数的第二个字符是数字?该参数表示要获取的记录数转换成十进制记录到全局变量packetnum还有参数?结束是数字?该参数中有非数字字符?该参数表示ip地址该参数表示数据报大小该参数表示主机名是“r”?显示用户帮助设标志位recordflag为turei=i+1记录到变量lpdest中记录到变量datasize中记录到变量lpdest中 图4.3 参数获取流程图4.ping()函数流程图ping()函数是本程序的核心部分它调用其他模块的函数来实现,其主要步骤包括创建接字,设置路由选项(如果需要的话)、设置接收和发送超时值、名字解析(如果需要的话)、分配内存、创建icmp报文、发送icmp请求报文、接收icmp应答报文和解读icmp报文。其执行流程如图4.4所示。开始创建原始套接字创建成功?记录路由?设置接收和发送超时值为每个icmp设置路由选项设置成功?名字解析?根据主机名获取各种参数获取成功?设置目的地址各项字段根据icmp报文大小分配内存分配成功创建icmp报文发送icmp请求发送成功?超时发送?输出超时发送接收icmp应答输出失败信息接收成功?超时接收?输出失败信息输出超时接收读取icmp数据报文记录数达到指定值?图4.4 ping函数流程图5. 代码ping的代码:#pragma comment(lib, ws2_32.lib)1. 程序预处理/*导入库文件*/#pragma comment( lib, ws2_32.lib )/*加载头文件*/#include #include #include #include #include /*定义常量*/*表示要记录路由*/#define ip_record_route 0x7/*默认数据报大小*/#define def_packet_size 32 /*最大的icmp数据报大小*/#define max_packet 1024 /*最大ip头长度*/#define max_ip_hdr_size 60 /*icmp报文类型,回显请求*/ #define icmp_echo 8/*icmp报文类型,回显应答*/ #define icmp_echoreply 0/*最小的icmp数据报大小*/#define icmp_min 8/*自定义函数原型*/void initping();void userhelp();void getargments(int argc, char* argv); ushort checksum(ushort *buffer, int size);void fillicmpdata(char *icmp_data, int datasize);void freeres();void decodeipoptions(char *buf, int bytes);void decodeicmpheader(char *buf, int bytes, sockaddr_in* from);void pingtest(int timeout);/*ip报头字段数据结构*/typedef struct _iphdr unsigned int h_len:4; /*ip报头长度*/ unsigned int version:4; /*ip的版本号*/ unsigned char tos; /*服务的类型*/ unsigned short total_len; /*数据报总长度*/ unsigned short ident; /*惟一的标识符*/ unsigned short frag_flags; /*分段标志*/ unsigned char ttl; /*生存期*/ unsigned char proto; /*协议类型(tcp、udp等)*/ unsigned short checksum; /*校验和*/ unsigned int sourceip; /*源ip地址*/ unsigned int destip; /*目的ip地址*/ ipheader;/*icmp报头字段数据结构*/typedef struct _icmphdr byte i_type; /*icmp报文类型*/ byte i_code; /*该类型中的代码号*/ ushort i_cksum; /*校验和*/ ushort i_id; /*惟一的标识符*/ ushort i_seq; /*序列号*/ ulong timestamp; /*时间戳*/ icmpheader;/*ip选项头字段数据结构*/typedef struct _ipoptionhdr unsigned char code; /*选项类型*/ unsigned char len; /*选项头长度*/ unsigned char ptr; /*地址偏移长度*/ unsigned long addr9; /*记录的ip地址列表*/ ipoptionheader;/*定义全局变量*/socket m_socket;ipoptionheader ipoption;sockaddr_in destaddr;sockaddr_in sourceaddr;char *icmp_data;char *recvbuf;ushort seq_no ;char *lpdest;int datasize;bool recordflag;double packetnum;bool sucessflag;初始化模块/*初始化变量函数*/ void initping() wsadata wsadata; icmp_data = null; seq_no = 0; recvbuf = null; recordflag = false; lpdest = null; datasize = def_packet_size; packetnum = 5; sucessflag = false; /*winsock初始化*/ if (wsastartup(makeword(2, 2), &wsadata) != 0) /*如果初始化不成功则报错,getlasterror()返回发生的错误信息*/ printf(wsastartup() failed: %dn, getlasterror(); return ; m_socket = invalid_socket;功能控制模块/*显示信息函数*/void userhelp() printf(userhelp: ping -r data sizen); printf( -r record routen); printf( -n record amountn); printf( host remote machine to pingn); printf( datasize can be up to 1kbn); exitprocess(-1); /*获取ping选项函数*/void getargments(int argc,char* argv) int i; int j; int exp; int len; int m; /*如果没有指定目的地地址和任何选项*/ if(argc = 1) printf(nplease specify the destination ip address and the ping option as follow!n); userhelp(); for(i = 1; i =1;j-,exp+) /*根据argvij中的ascii值计算要获取的记录条数(十进制数)*/ packetnum += (double)(argvij-48)*pow(10,exp); else switch (tolower(argvi1) /*选项指示要获取路由信息*/ case r: recordflag = true; break; /*没有按要求提供选项*/ default: userhelp(); break; /*参数是数据报大小或者ip地址*/ else if (isdigit(argvi0) for(m=1;m 1) cksum += *buffer+; size -= sizeof(ushort); if (size) cksum += *(uchar*)buffer; /*对每个16bit进行二进制反码求和*/ cksum = (cksum 16) + (cksum & 0xffff); cksum += (cksum 16); return (ushort)(cksum);/*填充icmp数据报字段函数*/void fillicmpdata(char *icmp_data, int datasize) icmpheader *icmp_hdr = null; char *datapart = null; icmp_hdr = (icmpheader*)icmp_data; /*icmp报文类型设置为回显请求*/ icmp_hdr-i_type = icmp_echo; icmp_hdr-i_code = 0; /*获取当前进程ip作为标识符*/ icmp_hdr-i_id = (ushort)getcurrentprocessid(); icmp_hdr-i_cksum = 0; icmp_hdr-i_seq = 0; datapart = icmp_data + sizeof(icmpheader); /*以数字0填充剩余空间*/ memset(datapart,0,datasize-sizeof(icmpheader);/*释放资源函数*/void freeres() /*关闭创建的套接字*/ if (m_socket != invalid_socket) closesocket(m_socket); /*释放分配的内存*/ heapfree(getprocessheap(), 0, recvbuf); heapfree(getprocessheap(), 0, icmp_data); /*注销wsastartup()调用*/ wsacleanup(); return ;数据报解读模块/*解读ip选项头函数*/void decodeipoptions(char *buf, int bytes) ipoptionheader *ipopt = null; in_addr inaddr; int i; hostent *host = null; /*获取路由信息的地址入口*/ ipopt = (ipoptionheader *)(buf + 20); printf(rr: ); for(i = 0; i ptr / 4) - 1; i+) inaddr.s_un.s_addr = ipopt-addri; if (i != 0) printf( ); /*根据ip地址获取主机名*/ host = gethostbyaddr(char *)&inaddr.s_un.s_addr,sizeof(inaddr.s_un.s_addr), af_inet); /*如果获取到了主机名,则输出主机名*/ if (host) printf(%-15s) %sn, inet_ntoa(inaddr), host-h_name); /*否则输出ip地址*/ else printf(%-15s)n, inet_ntoa(inaddr); return;/*解读icmp报头函数*/void decodeicmpheader(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; /*计算ip报头的长度*/ iphdrlen = iphdr-h_len * 4; tick = gettickcount(); /*如果ip报头的长度为最大长度(基本长度是20字节),则认为有ip选项,需要解读ip选项*/ if (iphdrlen = max_ip_hdr_size) & (!icmpcount) /*解读ip选项,即路由信息*/ decodeipoptions(buf, bytes); /*如果读取的数据太小*/ if (bytes sin_addr); icmphdr = (icmpheader*)(buf + iphdrlen); /*如果收到的不是回显应答报文则报错*/ if (icmphdr-i_type != icmp_echoreply) printf(nonecho type %d recvdn, icmphdr-i_type); return; /*核实收到的id号和发送的是否一致*/ if (icmphdr-i_id != (ushort)getcurrentprocessid() printf(someone elses packet!n); return ; sucessflag = true; /*输出记录信息*/ printf(%d bytes from %s:, bytes, inet_ntoa(from-sin_addr); printf( icmp_seq = %d. , icmphdr-i_seq); printf( time: %d ms, tick - icmphdr-timestamp); printf(n); icmpcount+; return;ping 测试模块/*ping函数*/void pingtest(int timeout) int ret; int readnum; int fromlen; struct hostent *hp = null; /*创建原始套接字,该套接字用于icmp协议*/ m_socket = wsasocket(af_inet, sock_raw, ipproto_icmp, null, 0,wsa_flag_overlapped); /*如果套接字创建不成功*/ if (m_socket = invalid_socket) printf(wsasocket() failed: %dn, wsagetlasterror(); return ; /*若要求记录路由选项*/ if (recordflag) /*ip选项每个字段用0初始化*/ zeromemory(&ipoption, sizeof(ipoption); /*为每个icmp包设置路由选项*/ ipoption.code = ip_record_route; ipoption.ptr = 4; ipoption.len = 39; ret = setsockopt(m_socket, ipproto_ip, ip_options,(char *)&ipoption, sizeof(ipoption); if (ret = socket_error) printf(setsockopt(ip_options) failed: %dn,wsagetlasterror(); /*设置接收的超时值*/ readnum = setsockopt(m_socket, sol_socket, so_rcvtimeo,(char*)&timeout, sizeof(timeout); if(readnum = socket_error) printf(setsockopt(so_rcvtimeo) failed: %dn,wsagetlasterror(); return ; /*设置发送的超时值*/ timeout = 1000; readnum = setsockopt(m_socket, sol_socket, so_sndtimeo,(char*)&timeout, sizeof(timeout); if (readnum = socket_error) printf(setsockopt(so_sndtimeo) failed: %dn,wsagetlasterror(); return ; /*用0初始化目的地地址*/ memset(&destaddr, 0, sizeof(destaddr); /*设置地址族,这里表示使用ip地址族*/ destaddr.sin_family = af_inet; if (destaddr.sin_addr.s_addr = inet_addr(lpdest) = inaddr_none) /*名字解析,根据主机名获取ip地址*/ if (hp = gethostbyname(lpdest) != null) /*将获取到的ip值赋给目的地地址中的相应字段*/ memcpy(&(destaddr.sin_addr), hp-h_addr, hp-h_length); /*将获取到的地址族值赋给目的地地址中的相应字段*/ destaddr.sin_family = hp-h_addrtype; printf(destaddr.sin_addr = %sn, inet_ntoa(destaddr.sin_addr); /*获取不成功*/ else printf(gethostbyname() failed: %dn,wsagetlasterror(); return ; /*数据报文大小需要包含icmp报头*/ datasize += sizeof(icmpheader); /*根据默认堆句柄,从堆中分配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(heapalloc() failed: %dn, getlasterror(); return ; /* 创建icmp报文*/ memset(icmp_data,0,max_packet); fillicmpdata(icmp_data,datasize); while(1) static int ncount = 0; int writenum; /*超过指定的记录条数则退出*/ if (ncount+ = packetnum) break; /*计算校验和前要把校验和字段设置为0*/ (icmpheader*)icmp_data)-i_cksum = 0; /*获取操作系统启动到现在所经过的毫秒数,设置时间戳*/ (icmpheader*)icmp_data)-timestamp = gettickcount(); /*设置序列号*/ (icmpheader*)icmp_data)-i_seq = seq_no+; /*计算校验和*/ (icmpheader*)icmp_data)-i_cksum = checksum(ushort*)icmp_data, datasize); /*开始发送icmp请求 */ writenum = sendto(m_socket, icmp_data, datasize, 0,(struct sockaddr*)&destaddr, sizeof(destaddr); /*如果发送不成功*/ if (writenum = socket_error) /*如果是由于超时不成功*/ if (wsagetlasterror() = wsaetimedout) printf(timed outn); continue; /*其他发送不成功原因*/ printf(sendto() failed: %dn, wsagetlasterror(); return ; /*开始接收icmp应答 */ fromlen = sizeof(sourceaddr); readnum = recvfrom(m_socket, recvbuf, max_packet, 0,(struct sockaddr*)&sourceaddr, &fromlen); /*如果接收不成功*/ if (readnum = socket_error) /*如果是由于超时不成功*/ if (wsagetlasterror() = wsaetimedout) printf(timed outn); continue; /*其他接收不成功原因*/ printf(recvfrom() failed: %dn, wsagetlasterror(); return ; /*解读接收到的icmp数据报*/ decodeicmpheader(recvbuf, readnum, &sourceaddr); 主函数int main(int argc, char* argv) initping(); getargments(argc, argv); pingtest(1000); /*延迟1秒*/ sleep(1000); if(sucessflag) printf(nping end, you have got %.0f records!n,packetnum); else printf(ping end, no record!); freeres(); getchar(); return 0; echo的代码:package a2;import .*;import java.io.*;public class echoserverpublic final static int echoport=1101;/echo服务器端口1011public static void main (string args) tryserversocket server=new serversocket(echoport);/创建一个服务器端套接字对象socket connection=null;/创建套接字对象while(true)tryconnection=server.accept();/阻塞方法,侦听并接受到此套接字的连接bufferedreader reader=new bufferedreader(new inputstreamreader(connection.getinputstream();/连接成功,创建一个bufferedreader对象,返回此套接字的输入流printwriter writer=new printwriter(new bufferedwriter(new outputstreamwriter(connection.getoutputstream(),true);/创建一个printwriter对象,用于向套接字写入数据 string str=reader.readline(); /从套接字读取一行 system.out.println(str); /打印该行数据 writer.println(str); /在向套接字中写入该行数据catch(ioexception ex)system.out.println(在读写数据的过程中发生错误!);ex.printstacktrace(); /异常处理,简单打印异常信息和异常栈finallytryif(connection!=null)connection.close(); /关闭套接字对象catch(io
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 计算机科学核心知识试题及答案
- 法学概论与人文社会科学的交融试题及答案
- 山东省威海文登区四校联考2025届七下数学期末综合测试模拟试题含解析
- 信息处理技术员考试复习问题集试题及答案
- 增强班级合作意识的工作措施计划
- 法治文化的内涵与外延试题及答案
- 班级理论知识竞赛的组织与实施计划
- 企业治理与决策科学的总结计划
- 如何提升工作效率的策略计划
- 基于数据分析的急诊业务提升计划
- 【MOOC】理解马克思-南京大学 中国大学慕课MOOC答案
- JGT266-2011 泡沫混凝土标准规范
- 人教版六年级下册数学第五、六单元测试题及答案
- 常用H型钢理论重量表格
- 浙江省温州市2022年初中科学中考试题及参考答案
- 临检、免检、微检 知识点整理
- 食品经营操作流程图
- 排桩+锚索深基坑安全专项施工方案
- 德州信息技术中考备考样题4综合
- 南水北调沿运灌区的基本概况
- 海外医疗服务委托合同协议书范本
评论
0/150
提交评论