网站首页 公文大全 个人文档 实用范文 讲话致辞 实用工具 心得体会 哲学范文 总结范文 范文大全 报告 合同 文书 信函 实用
  • 劳动合同
  • 租赁合同
  • 买卖合同
  • 施工合同
  • 销售合同
  • 工程合同
  • 转让协议
  • 借款合同
  • 百花范文网 > 合同 > 劳动合同 > Ping程序的设计与实现课程设计_计算机网络ping实验

    Ping程序的设计与实现课程设计_计算机网络ping实验

    时间:2021-06-02 03:01:40来源:百花范文网本文已影响

    计算机网络课程设计报告 设计名称 Ping程序的设计与实现 专业班级 同组人姓名 指导教师 成 绩 一、设计目的和要求 1、实验目的 利用ICMP数据包、C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间的连通情况。通过本程序的训练,使学生熟悉ICMP报文结构,使学生对ICMP有更深的理解,掌握Ping程序的设计方法,掌握网络编程的方法和技巧,从而编写出功能更强大的程序。

    2、 实验要求:输出参考系统自带ping程序,命令行运行:ping ip;

    二、 设计说明 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, Window XP操作系统平台 4. 设计中的难点和重点 首先遇到的问题就是套接字文件的问题。套接字所需要的文件有头文件Winsocket2.h、库文件WS2_32.LIB、动态库W32_32.DLL。创建套接字的时候参数的以及在创建套接字之前必须首先使用WSAStartup函数、在使用完套接字之后要释放内存资源,关闭套接字这些问题都是以前未接触过的。所以在写程序的时候需要查阅大量的资料,弄懂这些问题。其次,在套接字问题解决之后,遇到的难题,也是比较重要的问题就是如何实现ICMP报文的发送和接受,以及怎样判断发送、接收超时或者找不到目的主机。最后在程序调试的时候总是出现这样或那样的错误,比如头文件错误、动态库无法导入、编辑器环境不匹配等。

    5. 输入和输出条件 在程序运行后弹出的命令行界面下。输入IP地址,例如:59.69.172.18,回车键,在很短的时间内就能输出相关信息,若对方没有收到就会有“Requrest timed out !”输出。

    程序每运行一次就只能输出四行结果(前提是输入的地址有效),欲再次Ping其他地址必须要重新运行程序。输入时不能输入目标主机名,不然ping结果为“‘***’主机”。

    三、 系统详细设计 本程序主要是通过main()函数调用自定义函数以及其本身的一些功能,例如:打开socket动态库、设置接收和发送超时值、域名地址解析、分配内存、创建及初始化ICMP报文、发送ICMP请求报文、接收ICMP 应答报文以及解读应答报文和输出Ping结果,最后释放占用的资源其流程如下图所示。

    开始 定义及初始化各个全局变量 判断WSAStartup函数是否调用成功 输出调用失败 否 创建套接字以及设置socket接收超时,发送超时选项;

    是 输入PING的IP地址 解析输入内容,设置PING参数 创建及填充ICMP数据报文 判断是否已发送四次 Break; 发送,接收以及解析数据包 输出PIING结果 是 结束 清除残余 否 校验和函数、释放资源函数:
    Checksum开始 定义初始化cksum (size > 1) 确定cksum及size大小 是 if (size) 计算校验cksum,获得结果 cksum += *(UCHAR*)buffer; 否 结束 Cleanup开始 if (m_hSocket != INVALID_SOCKET) 关闭套接字 释放占用资源 清除ICMP包数据以及接受缓冲区 F WSACleanup(); 结束 解读ICMP报首部函数流程图:
    DecodeICMPHeader开始 定义相关变量以及初始化;

    tick = GetTickCount(); 为我们所要的回应报文;

    是 输出不是我们所要;

    tick0[icmpcount]=tick -icmphdr->timestamp; 判断时间是否小于1ms printf(“Reply from %s: dytes=%d time<1ms icmp_seq = %d\n“,inet_ntoa(from->sin_addr), bytes, icmphdr->i_seq ); printf(“Reply from %s: dytes=%d time=%d icmp_seq = %d\n“,inet_ntoa(from->sin_addr), bytes,tick0[icmpcount], icmphdr->i_seq); 是 是 icmpcount++; 结束 结束 否 四、程序源代码及注释 #pragma comment(lib,“ws2_32.lib“) #include <winsock2.h>//创建套接字头文件 #include <ws2tcpip.h> #include <stdio.h>//标准输入输出函数 #include <stdlib.h>//实用程序库函数 #include <string.h> 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 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; //惟一的标识符 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=NULL; //填充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 = 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 & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } //解读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; iphdrlen = iphdr->h_len * 4; tick = GetTickCount(); if (bytes < iphdrlen + ICMP_MIN) { printf(“Too few bytes from %s \r\n“,inet_ntoa(from->sin_addr)); } icmphdr = (IcmpHeader*)(buf + iphdrlen); if (icmphdr->i_type != ICMP_ECHOREPLY) { printf(“nonecho type %d received \r\n“, icmphdr->i_type); } if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) { printf(“其他程序的回应报文! \t错误代码 %d\n“, WSAGetLastError()); } DWORD tick0[4]; tick0[icmpcount]=tick - icmphdr->timestamp; if(tick0[icmpcount]<1) printf(“Reply from %s: bytes=%d time<1ms icmp_seq =%d\n“,inet_ntoa(from->sin_addr), bytes, icmphdr->i_seq ); else printf(“Reply from %s: bytes=%d time=%dms icmp_seq = %d\n“,inet_ntoa(from->sin_addr), bytes,tick0[icmpcount], icmphdr->i_seq); icmpcount++; //return; } //释放资源函数 void Cleanup() { if (m_hSocket != INVALID_SOCKET) closesocket(m_hSocket); HeapFree(GetProcessHeap(), 0, recvbuf); HeapFree(GetProcessHeap(), 0, icmp_data); WSACleanup(); } //主函数 void main() { WSADATA wsaData; char a[100]; 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!“); } 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_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)//地址转化 { 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; //将获取到的地址族值赋给目的地地址中的相应字段 } else { printf(“不能找到名为 %s 的主机\t错误代码 %d\n“,lpdest, WSAGetLastError());//获取不成功 exit(0); } } printf(“Pinging %s with 64 bytes of data: \n\n“, inet_ntoa(m_addrDest.sin_addr)); 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报文 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++;//设置序列号 ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, datasize);//计算校验和 bwrote = sendto(m_hSocket, icmp_data, datasize, 0, (struct sockaddr*)&m_addrDest, sizeof(m_addrDest));//开始发送ICMP请求 if (bwrote == SOCKET_ERROR)//如果发送不成功 { if (WSAGetLastError() == WSAETIMEDOUT) //如果是由于超时不成功 { printf(“Requrest timed out ! \r\n“); continue; } printf(“目标不可达!\t错误代码 %d\n“, WSAGetLastError());//其他发送不成功原因 continue; } if (bwrote < datasize) { printf(“Wrote %d bytes \r\n“, bwrote); } int fromlen = sizeof(m_addrFrom);//开始接收ICMP应答 bread=recvfrom(m_hSocket,recvbuf,MAX_PACKET,0,(struct sockaddr*)&m_addrFrom, &fromlen); if (bread == SOCKET_ERROR)//如果接收不成功 { if (WSAGetLastError() == WSAETIMEDOUT) //如果是由于超时不成功 { printf(“Requrest timed out !\r\n“); continue; } printf(“接收数据函数调用错误!\t错误代码 %d\n“, WSAGetLastError());//其他接收不成功原因 exit(0); } DecodeICMPHeader(recvbuf, bread, &m_addrFrom);//解读接收到的ICMP数据报 } Cleanup(); } 五、 相关注释 1、GetCurrentProcessId() 函数原型:DWORD WINAPI GetCurrentProcessId(VOID);    说明: 获取当前进程的标示符(PID)    返回值:返回一个标示符(PID)    库文件:kernel32.dll 2、 GetTickcount() 函数原型:DWORD GetTickCount(void); 说明:常常用来判断某个方法执行的时间。

    返回值:返回从操作系统启动到当前所经过的毫秒数,返回值以32位的双字类型DWORD存储,因此可以存储的最大值是2-1 ms约为49.71天,因此若系统运行时间超过49.71天时,这个数就会归0,MSDN中也明确的提到了:“Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.“。因此,如果是编写服务器端程序,此处一定要万分注意,避免引起意外的状况。

    3、inet_ntoa() 函数功能:将网络地址转换成“.”点隔的字符串格式。

       所需库:winsock.h 也可以使用:头文件 Winsock2.h 函数原型:char FAR* PASCAL FAR inet_ntoa( struct in_addr in);       in:一个表示Internet主机地址的结构。

       注释:本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。

      返回值:若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NULL。其中的数据应在下一个WINDOWS套接口调用前复制出来。

    4、HeapFree() 功能:从一个堆中释放一个由HeapAlloc或HeapReAlloc函数定位的内存块。

    语法BOOL WINAPI HeapFree( __in HANDLE hHeap, __in DWORD dwFlags, __in LPVOID lpMem ); 如果函数成功,返回值为非零,如果失败,返回零值。应用程序可以通过调用GetLastError函数来获取更多的错误信息。

    当内存块被释放时候,就不能再次对其进行引用了,而且,所有的信息都将消失。如果你想要这些信息,请不要释放包含这些信息的内存。诸如能够返回内存信息(如内存大小)等的函数对释放过了的内存将无效。对同一内存指针进行两次释放将会导致堆崩溃。

    5、 getprocessheap(): 用以获取和调用过程的堆句柄 6、 WSACleanup() 功能:中止Winsock 2 DLL (Ws2_32.dll) 的使用. 头文件:Winsock2.h 函数原型:int PASCAL FAR WSACleanup ( void ); 返回值:操作成功返回值为0;
    否则返回值为SOCKET_ERROR,可以通过调用WSAGetLastError获取错误代码。在一个多线程的环境下,WSACleanup()中止了Windows Sockets在所有线程上的操作. 7、 closesocket() 简述:关闭一个套接口。

       头文件:#include <winsock.h>    函数原型:int PASCAL FAR closesocket( SOCKET s);    s:一个套接口的描述字。

    返回值:如无错误发生,则closesocket()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

    8、 WSAStartup() 简述:创建一个与指定传送服务提供者捆绑的套接口,可选地创建或加入一个套接口组。此函数为socket()的扩展版本,其功能都是创建一个原始套接字。使用时需要包含 winsock2.h 头文件和链接wsock32.lib库。

    定义:SOCKET WSAAPI WSASocket ( int af, int type, int protocol, LPPROTOCOL_INFO lpProtocolInfo, Group g, int iFlags);    af:地址族描述。目前仅支持AF_INET格式,亦即ARPA Internet地址格式。

       type:新套接口的类型描述。

       protocol:套接口使用的特定协议,如果调用者不愿指定协议则定为0。

      lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。

       g:套接口组的描述字。

       iFlags:套接口属性描述。

    返回值:若无错误发生,WSASocket()返回新套接口的描述字。否则的话,返回 INVALID_SOCKET,应用程序可定调用WSAGetLastError()来获取相应的错误代码。

    9、 setsockopt() 功能:设置套接口的选项。

       头文件:#include <winsock.h>    函数原型:int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR *optval, int optlen);    s:标识一个套接口的描述字。

       level:选项定义的层次;
    目前仅支持SOL_SOCKET和IPPROTO_TCP层次。

       optname:需设置的选项。

       optval:指针,指向存放选项值的缓冲区。

       optlen:optval缓冲区长度。

    10、memset() 函数原型:void *memset(void *s,int c,size_t n)    总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c。

    memset()的深刻内涵:用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为memset(a, '\0', sizeof(a)); 11、 gethostbyname() 说明:返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针。

    返回对应于给定主机名的主机信息。

       头文件:#include <winsock2.h>    函数原型:struct hostent FAR *PASCAL FAR gethostbyname(const char FAR * name);    name:指向主机名的指针。

    返回值:如果没有错误发生,gethostbyname()返回如上所述的一个指向hostent结构的指针,否则,返回一个空指针。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。

    12、memcpy() 函数原型:void *memcpy(void *dest, const void *src, size_t n); 说明:由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。

    头文件:#include <string.h> 返回值:函数返回一个指向dest的指针。与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

    13、 WSAGetLastError()   简述: 获得上次失败操作的错误状态。   头文件:#include <winsock.h>    函数原型:int PASCAL FAR WSAGetLastError ( void );    注释: 本函数返回上次发生的网络错误.当一特定的Windows Sockets API函数指出一个错误已经发生,本函数就应调用来获得对应的错误代码.    返回值: 返回值指出了本线程进行的上一次Windows Sockets API函数调用时的错误代码. 14、sendto() 说明:向一指定目的地发送数据。

    头文件:#include <winsock.h> 函数原型:int PASCAL FAR sendto( SOCKET s, const char FAR* buf, int len, int flags, const struct sockaddr FAR* to, int tolen); s为服务器端监听的套接字。

    buf为欲发送数据缓冲区的指针。

    len为发送数据缓冲区的长度。

    flags为数据发送标记。

    to:(可选)指针,指向目的套接口的地址。

    tolen:to所指地址的长度。即sizeof(tolen) 返回值:发送数据的字符数. 注释:sendto()适用于已连接的数据报或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。IP包最大长度在WSAStartup()调用返回的WSAData的iMaxUdpDg元素中。如果数据太长无法自动通过下层协议,则返回WSAEMSGSIZE错误,数据不会被发送。

    请注意成功地完成sendto()调用并不意味着数据传送到达。sendto()函数主要用于SOCK_DGRAM类型套接口向to参数指定端的套接口发送数据报。对于SOCK_STREAM类型套接口,to和tolen参数被忽略;
    这种情况下sendto()等价于send()。

    15、 recvfrom()    函数原型:ssize_t recvfrom(int sockfd,void *buf,int len,unsigned int flags, struct sockaddr *from,socket_t *fromlen);    ssize_t 相当于 int,socket_t 相当于int ,这里用这个名字为的是提高代码的自说明性。

       函数说明: recvfrom()用来接收远程主机经指定的socket传来的数据,并把数据传到由参数buf指向的内存空间,参数len为可接收数据的最大长度.参数flags一般设0,其他数值定义参考recv().参数from用来指定欲传送的网络地址,结构sockaddr请参考bind()函数.参数fromlen为sockaddr的结构长度.    返回值: 成功则返回接收到的字符数,失败返回-1. 16、 结构体sockaddr_in Step 1: 初始化该数据结构 struct sockaddr_in my_addr; Step 2: 填充信息 my_addr.sin_family = AF_INET; my_addr.sin_port = htons (6666); my_addr.sin_addr.s_addr = htonl (INADDR_ANY); 所以my_addr.sin_addr.s_addr是ip地址。

    六、 实验数据、结果分析 Ping任意IP地址:
    在连接网络的情况下,Ping域名:
    Ping IP地址超时:
    对Ping后返回结果的分析:
      1.Request timed out(请求超时)   (1) 对方已关机,或者网络上根本没有这个地址:比如在上图中Ping 59.69.172.53   (2)对方与自己不在同一网段内,通过路由也无法找到对方,但有时对方确实是存在的,当然不存在也是返回超时的信息。

      (3)对方确实存在,但设置了ICMP数据包过滤(比如防火墙设置)。

      (4)错误设置IP地址    正常情况下,一台主机应该有一个网卡,一个IP地址,或多个网卡,多个IP地址(这些地址一定要处于不同的IP子网)。但如果一台电脑的“拨号网络适配器”(相当于一块软网卡)的TCP/IP设置中,设置了一个与网卡IP地址处于同一子网的IP地址,这样,在IP层协议看来,这台主机就有两个不同的接口处于同一网段内。当从这台主机Ping其他的机器时,会存在这样的问题:
      A.主机不知道将数据包发到哪个网络接口,因为有两个网络接口都连接在同一网段   B.主机不知道用哪个地址作为数据包的源地址。因此,从这台主机去Ping其他机器,IP层协议会无法处理,超时后,Ping 就会给出一个“超时无应答”的错误信息提示。但从其他主机Ping这台主机时,请求包从特定的网卡来,ICMP只须简单地将目的、源地址互换,并更改一些标志即可,ICMP应答包能顺利发出,其他主机也就能成功Ping通这台机器了。

      2.Destination host Unreachable(目标不可达)   (1)对方与自己不在同一网段内,而自己又未设置默认的路由。

      (2)网线出了故障   这里要说明一下“destination host unreachable”和 “time out”的区别,如果所经过的路由器的路由表中具有到达目标的路由,而目标因为其他原因不可到达,这时候会出现“time out”,如果路由表中连到达目标的路由都没有,那就会出现“destination host unreachable”。

      3.Unknown host——不知名主机   这种出错信息的意思是,该远程主机的名字不能被域名服务器(DNS)转换成IP地址。故障原因可能是域名服务器有故障,或者其名字不正确,或者网络管理员的系统与远程主机之间的通信线路有故障。

      7.Ping 127.0.0.1:127.0.0.1是本地循环地址 六、总结 通过设计程序,真正了解了ICMP的结构。编写过程中,一些基本的常见的函数不会应用,这使我发现自己知识的匮乏,在以后的学习过程中得要好好的努力,多阅读一些复杂的程序,了解一个基本的函数,算法和精良的编程思想,更要多动手写一些有一定难度的程序,我们不应该害怕写程序出错,应该大胆地写出自己的想法,出现错误去解决错误就能找出自己知识的漏洞和模糊点。我们还可以通过阅读别人错误的程序,试着帮别人查找错误,这样证书技能头脑中的规则还能发现一些初学者一番的错误,使自己少走弯路。

    通过整个程序和编写文档过程,感觉自己的能力还远远没达到老师的要求的层面上,恐怕还要继续努力啊。

    相关热词搜索:课程设计 程序 设计 Ping程序的设计与实现课程设计 计算机网络ping实验 ping是如何实现的

    • 范文大全
    • 说说大全
    • 学习资料
    • 语录
    • 生肖
    • 解梦
    • 十二星座