网络检测报告

湖南商学院

《计算机软件设计》设计(实习)

题 目       网络状态检测            

计算机与电子工程学院

20##12


课程设计(实习)评审表

课程设计(实习)作品验收表

注:1. 除“验收情况”栏外,其余各栏均由学生在作品验收前填写。

2. “验收情况”栏由验收小组按实际验收的情况如实填写。


目录

1 课程设计任务与要求................................... 1

1.1 课程设计任务.................................... 1

1.2 问题提出........................................ 1

2 总体设计............................................ 2

2.1总体设计思想及开发原理............................ 2

2.1.1基于WINDOWS SOCKET的应用开发介绍........... 2

2.1.2 ICMP数据报................................ 3

3 详细设计............................................ 4

3.1 确定所需模块.................................... 4

3.2 各子模块功能描述................................. 5

3.2.1.定义IP首部格式............................ 5

3.2.2.定义ICMP首部格式.......................... 5

3.2.3.定义ICMP回应请求.......................... 6

3.2.4.定义ICMP回应答复.......................... 6

3.2.5.计算校验和................................. 6

3.2.6.发送回应请求函数........................... 7

3.2.7.接收应答回复并进行解析...................... 9

3.2.8.等待回应答复,使用select机制.............. 10

3.2.9. Ping功能实现............................ 10

3.3 模块间调用关系................................. 13

4 系统实现与测试..................................... 14

4.1系统测试用例的设计.............................. 14

4.2系统测试结果.................................... 14

5 课程设计总结....................................... 15

6 软件使用说明书..................................... 16

参考文献............................................. 16

附录:源代码......................................... 17


C/C++实现网络连接状态的检测

1 课程设计任务与要求

1.1 课程设计任务

通过本课程设计加深对C语言和相关技术的理解,实践和锻炼计算机软件的设计能力、系统实现和调试能力。培养严谨的科学实验作风和良好的工程素质,从而提高学生的动手能力、分析问题和解决问题的能力。更加符合学院培养综合型技术人才的目标和要求。

1.2 问题提出

PING是DOS命令,一般用于检测网络通与不通 ,也叫时延,其值越大,速度越慢。

PING (Packet Internet Grope),因特网包探索器,用于测试网络连接量的程序。Ping发送一个ICMP回声请求消息给目的地并报告是否收到所希望的ICMP回声应答。

它是用来检查网络是否通畅或者网络连接速度的命令。作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的:利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包,再要求对方返回一个同样大小的数据包来确定两台网络机器是否连接相通,时延是多少?

ping指的是端对端连通,通常用来作为可用性的检查, 但是某些病毒木马会强行大量远程执行ping命令抢占你的网络资源,导致系统变慢,网速变慢。严禁ping入侵作为大多数防火墙的一个基本功能提供给用户进行选择。通常的情况下你如果不用作服务器或者进行网络测试,可以放心的选中它,保护你的电脑。

2 总体设计

2.1总体设计思想及开发原理

2.1.1基于WINDOWS SOCKET的应用开发介绍

在WINDOWS95/98,WINDOWSNT进行WINSOCK开发使用的编程语言有很多,VC++,JAVA,DELPHI,VB等。其中VC时使用最普遍,和WINSOCK结合最紧密的。并且VC++对原来的WindowsSockets库函数进行了一系列封装,继而产生了CAsynSocket、CSocket、CSocketFile等类,它们封装着有关Socket的各种功能,是编程变得更加简单。但如果你是一个WINSOCK编程的初学者,那么建议你在一开始还是学习WINSOCK最基本的API函数进行编程,这样可以大大加深对WINSOCK的了解,对将来很有好处。

在VC中进行WINSOCK的API编程开发,需要使用到下面三个文件:

1、 WINSOCK.H: 这是WINSOCK API的头文件。

2 、WSOCK32.LIB: WINSOCK API连接库文件。在使用中,一点要把它作为项目的非缺省的连接库包含到项目文件中去。

3 、WINSOCK.DLL: WINSOCK的动态连接库,位于WINDOWS的安装目录下。DLL位于TCP/IP协议栈和应用程序之间。也就是说,WINSOCK管理与TCP/IP协议的接口。在一开始WINSOCK的应有开发时,你不必对TCP/IP协议有很深刻的了解。但是,如果想成为一个为网络编程的高手,就一定要对下层了解得十分清楚。

在网络编程中最常用的方案便是客户机/服务器模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。在这个时刻,服务程序被“惊醒”并且为客户提供服务-对客户的请求作出适当的反应。虽然基于连接协议(流套接字)的服务是设计客户机/服务器应用程序时的标准,但有些服务也是可以通过无连接协议(数据报套接字)提供的。

2.1.2 ICMP数据报

ICMP(Internet Control Message,网际控制报文协议)是为网关和目标主机而提供的一种差错控制机制,使它们在遇到差错时能把错误报告给报文源发方。ICMP协议是IP层的一个协议,但是由于差错报告在发送给报文源发方时可能也要经过若干子网,因此牵涉到路由选择等问题,所以ICMP报文需通过IP协议来发送。

ICMP数据报的数据发送前需要两级封装:首先添加ICMP报头形成ICMP报文,再添加IP报头形成IP数据报。如下图所示

IP报头

ICMP报头

ICMP数据报

IP报头格式

由于IP层协议是一种点对点的协议,而非端对端的协议,它提供无连接的数据报服务,没有端口的概念,因此很少使用bind()和connect()函数,若有使用也只是用于设置IP地址。发送数据使用sendto()函数,接收数据使用recvfrom()函数。

IP报头格式如下图:

图1

其中ping程序只使用以下数据:

IP报头长度IHL(Internet Header Length)――以4字节为一个单位来记录IP报头的长度,是上述IP数据结构的ip_hl变量。

生存时间TTL(Time To Live)――以秒为单位,指出IP数据报能在网络上停留的最长时间,其值由发送方设定,并在经过路由的每一个节点时减一,当该值为0时,数据报将被丢弃,是上述IP数据结构的ip_ttl变量。

ICMP报头格式

ICMP报文分为两种,一是错误报告报文,二是查询报文。每个ICMP报头均包含类型、编码和校验和这三项内容,长度为8位,8位和16位,其余选项则随ICMP的功能不同而不同。

Ping命令只使用众多ICMP报文中的两种:"请求回送"(ICMP_ECHO)和"请求回应"(ICMP_ECHOREPLY)。

这两种ICMP类型报头格式如下:

图2

3 详细设计

3.1 确定所需模块

根据PING的功能以及相关的数据结构,首先应该对程序进行初始化和函数库调用的设定。

#include <stdio.h>

#include <stdlib.h>

#include <winsock.h>

#pragma  comment (lib, "ws2_32.lib")

#define ICMP_ECHOREPLY      0  // ICMP回复应答

#define ICMP_ECHOREQ   8  // ICMP回应请求

#define REQ_DATASIZE 32       // 请求数据报大小

可以将该程序主要分成以下几个调用模块:

1.定义IP首部格式

2.定义ICMP首部格式

3.定义ICMP回应请求

4.定义ICMP回应答复

5.计算校验和

6.发送回应请求函数

7.接收应答回复并进行解析

8.等待回应答复,使用select机制

9.Ping功能实现

3.2 各子模块功能描述

3.2.1.定义IP首部格式

typedef struct _IPHeader

{

      u_char  VIHL;                // 版本和首部长度

      u_char   ToS;                     // 服务类型

      u_short  TotalLen;             // 总长度

      u_short  ID;                // 标识号

      u_short  Frag_Flags;         // 段偏移量

      u_char   TTL;                    // 生存时间

      u_char   Protocol;              // 协议

      u_short  Checksum;          // 首部校验和

      struct     in_addr SrcIP;     // 源IP地址

      struct     in_addr DestIP;  // 目的地址

}IPHDR, *PIPHDR;

3.2.2.定义ICMP首部格式

typedef struct _ICMPHeader

{

      u_char   Type;                   // 类型

      u_char   Code;                  // 代码

      u_short  Checksum;          // 首部校验和

      u_short  ID;                       // 标识

      u_short  Seq;                     // 序列号

      char Data;                   // 数据

}ICMPHDR, *PICMPHDR;

3.2.3.定义ICMP回应请求

typedef struct _ECHOREQUEST

{

      ICMPHDR icmpHdr;

      DWORD      dwTime;

      char cData[REQ_DATASIZE];

}ECHOREQUEST, *PECHOREQUEST;

3.2.4.定义ICMP回应答复

typedef struct _ECHOREPLY

{

      IPHDR  ipHdr;

      ECHOREQUEST      echoRequest;

      char    cFiller[256];

}ECHOREPLY, *PECHOREPLY;

3.2.5.计算校验和

u_short checksum(u_short *buffer, int len)

{

      register int nleft = len;

      register u_short *w = buffer;

      register u_short answer;

      register int sum = 0;

    // 使用32bit的累加器,进行16bit的反馈计算

      while( nleft > 1 )  {

             sum += *w++;

             nleft -= 2;

      }

      // 补全奇数位

      if( nleft == 1 ) {

             u_short  u = 0;

             *(u_char *)(&u) = *(u_char *)w ;

             sum += u;

      }

   // 将反馈的16bit从高位移至地位

      sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */

      sum += (sum >> 16);                /* add carry */

      answer = ~sum;                        /* truncate to 16 bits */

      return (answer);

}

3.2.6.发送回应请求函数

int SendEchoRequest(SOCKET s,struct sockaddr_in *lpstToAddr)

{

      static ECHOREQUEST echoReq;

      static nId = 1;

      static nSeq = 1;

      int nRet;

      // 填充回应请求消息

      echoReq.icmpHdr.Type           = ICMP_ECHOREQ;

      echoReq.icmpHdr.Code          = 0;

      echoReq.icmpHdr.Checksum  = 0;

      echoReq.icmpHdr.ID               = nId++;

      echoReq.icmpHdr.Seq                    = nSeq++;

      // 填充要发送的数据(随便填写)

      for (nRet = 0; nRet < REQ_DATASIZE; nRet++)

             echoReq.cData[nRet] = ' '+nRet;

      // 储存发送的时间

      echoReq.dwTime = GetTickCount();

      // 计算回应请求的校验和

      echoReq.icmpHdr.Checksum = checksum((u_short *)&echoReq, sizeof(ECHOREQUEST));

      // 发送回应请求                                                        

      nRet = sendto(s,                                     // 建立起的套接字

                            (LPSTR)&echoReq,               // 发送的缓冲区内容

                            sizeof(ECHOREQUEST),

                            0,                                            // 标志位

                            (struct sockaddr*)lpstToAddr, // 发送的目标地址

                            sizeof(SOCKADDR_IN));   // 地址结构长度

      if (nRet == SOCKET_ERROR)

      {

             printf("sendto() error:%d\n",WSAGetLastError());

      }

      return (nRet);

}

3.2.7.接收应答回复并进行解析

DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)

{

      ECHOREPLY echoReply;

      int nRet;

      int nAddrLen = sizeof(struct sockaddr_in);

      //接收应答回复 

      nRet = recvfrom(s,                                 // 接收的套接字

                                  (LPSTR)&echoReply,       // 接收的缓冲区

                                  sizeof(ECHOREPLY),     // 缓冲区长度

                                  0,                                // 标识

                                  (LPSOCKADDR)lpsaFrom,   // 接收的地址

                                  &nAddrLen);                    // 地址结构长度

      // 检验接收结果

      if (nRet == SOCKET_ERROR)

      {

             printf("recvfrom() error:%d\n",WSAGetLastError());

      }

    // 记录返回的TTL

      *pTTL = echoReply.ipHdr.TTL;

      //返回应答时间

      return(echoReply.echoRequest.dwTime);         

}

3.2.8.等待回应答复,使用select机制

int WaitForEchoReply(SOCKET s)

{

      struct timeval timeout;

      fd_set readfds;

      readfds.fd_count = 1;

      readfds.fd_array[0] = s;

      timeout.tv_sec = 5;

    timeout.tv_usec = 0;

      return(select(1, &readfds, NULL, NULL, &timeout));

}

3.2.9. Ping功能实现

void Ping(char *pstrHost)

{

      SOCKET       rawSocket;

      LPHOSTENT lpHost;

      struct    sockaddr_in destIP;

      struct    sockaddr_in srcIP;

      DWORD        dwTimeSent;

      DWORD        dwElapsed;

      u_char    cTTL;

      int       nLoop;

      int       nRet;

      // 创建原始套接字,ICMP类型

      rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

      if (rawSocket == SOCKET_ERROR)

      {

             printf("socket() error:%d\n",WSAGetLastError());

             return;

      }

     

      // 检测目标主机

      lpHost = gethostbyname(pstrHost);

      if (lpHost == NULL)

      {

             printf("Host not found: %s\n", pstrHost);

             return;

      }

     

      // 设置目标机地址

      destIP.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));

      destIP.sin_family = AF_INET;

      destIP.sin_port = 0;

      // 提示开始进行Ping

      printf("\nPinging %s with %d bytes of data:\n",

                           inet_ntoa(destIP.sin_addr),

                           REQ_DATASIZE);

      // 发起多次Ping测试

      for (nLoop = 0; nLoop < 4; nLoop++)

      {

             //发送ICMP回应请求

             SendEchoRequest(rawSocket, &destIP);

             // 使用select()等待回复的数据

             nRet = WaitForEchoReply(rawSocket);

             if (nRet == SOCKET_ERROR)

             {

                    printf("select() error:%d\n",WSAGetLastError());

                    break;

             }

             if (!nRet)

             {

                    printf("\nRequest time out");

                    break;

             }

             //接收回复

             dwTimeSent = RecvEchoReply(rawSocket, &srcIP, &cTTL);

             // 计算花费的时间

             dwElapsed = GetTickCount() - dwTimeSent;

             printf("\nReply from %s: bytes=%d time=%ldms TTL=%d",

               inet_ntoa(srcIP.sin_addr),

                       REQ_DATASIZE,

               dwElapsed,

               cTTL);

      }

      printf("\n");

      nRet = closesocket(rawSocket); // 关闭套接字,释放资源

      if (nRet == SOCKET_ERROR)

      {

             printf("closesocket() error:%d\n",WSAGetLastError());

      }

}

3.3 模块间调用关系

根据相应模块的关系结构,制定出主函数的调用关系:

void main(int argc, char **argv)

{

    WSADATA wsd;

    int nRet;

      // 检测输入的参数

    if (argc != 2)

    {

             printf("\nUsage: ping hostname\n");

             return;

    }

    // 初始化Winsock

      if (WSAStartup(MAKEWORD(1,1), &wsd) != 0)

    {

        printf("加载Winsock失败!\n");

    }

      //开始Ping

      Ping(argv[1]);

      // 释放Winsock资源

    WSACleanup();

}

4 系统实现与测试

4.1系统测试用例的设计

由于基本测试环境的限制,以及抱着简单易操作、易实现的基本理念。所以采用个人电脑进行系统的测试。所使用的例子也是个人所熟悉的网址进行网络检测,即:http://www.hao123.com/

4.2系统测试结果

基本测试进行了两种状态的检测,一种是连接成功时的状态,另一种是没有连接成功。因为实验环境的影响,所以此次测试是在个人的计算机上进行的。实现第一种状态时连接好网络,打开相关网址(http://www.hao123.com/)显示出连接结果并有相应的数据输出。第二种状态则直接断开网络连接,再次运行程序。显示未发现相关信息。

图  程序运行截图

5 课程设计总结

通过此次课程设计,使我更加扎实的掌握了有关C语言程序设计方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。

过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!

课程设计诚然是一门专业课,给我很多专业知识以及专业技能上的提升,同时又是一门讲道课,一门辩思课,给了我许多道,给了我很多思,给了我莫大的空间。同时,设计让我感触很深。使我对抽象的理论有了具体的认识。通过这次课程设计,我掌握了C程序在DOS环境下运行的相关必备知识,以及对VC6.0的更深层次的掌握,对C语言编写的体会也更加的深刻。

我认为,在这学期的实验中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在实验课上,我们学会了很多学习的方法。而这是日后最实用的,真的是受益匪浅。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。这对于我们的将来也有很大的帮助。以后,不管有多苦,我想我们都能变苦为乐,找寻有趣的事情,发现其中珍贵的事情。就像中国提倡的艰苦奋斗一样,我们都可以在实验结束之后变的更加成熟,会面对需要面对的事情。

回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,但可喜的是最终都得到了解决。

此次设计也让我明白了思路即出路,有什么不懂不明白的地方要及时请教或上网查询,只要认真钻研,动脑思考,动手实践,就没有弄不懂的知识,收获颇丰。

6 软件使用说明书

在相关软件的使用过程中要注意在DOS模式下才可以运行。首先,单机开始菜单,运行CMD文件。弹出对话框。输入cd+程序所在文件夹,输入ping+所需检测的网址来测试相关的网络状态。(如程序运行截图所示)

注意使用时不可以直接双击PING.EXE文件运行程序。

参考文献

[1]. 谭浩强.C程序设计(第三版)[M].北京:清华大学出版社,2005

[2]. James F.Kurose,Kei W.Ross.陈鸣译.计算机网络自顶向下方法 [M].北京:机械工业出版社,2008

[3]. 谢希仁主编.计算机网络(第5版)[M].北京:电子工业出版社,2008

[4]. 孙忠秀主编.操作系统教程(第4版)[M].北京:高等教育出版社,2008

[5]. 孟彩霞主编.计算机软件基础 [M].西安:西安电子科技大学出版社,2003


附录:源代码

#include <stdio.h>

#include <stdlib.h>

#include <winsock.h>

#pragma  comment (lib, "ws2_32.lib")

#define ICMP_ECHOREPLY       0

#define ICMP_ECHOREQ    8

#define REQ_DATASIZE 32

typedef struct _IPHeader

{

       u_char  VIHL;

       u_char     ToS;

       u_short    TotalLen;

       u_short    ID;

       u_short    Frag_Flags;

       u_char     TTL;

       u_char     Protocol;

       u_short    Checksum;

       struct      in_addr SrcIP;

       struct      in_addr DestIP;

}IPHDR, *PIPHDR;

typedef struct _ICMPHeader

{

       u_char     Type;

       u_char     Code;

       u_short    Checksum;

       u_short    ID;

       u_short    Seq;

       char Data;

}ICMPHDR, *PICMPHDR;

typedef struct _ECHOREQUEST

{

       ICMPHDR icmpHdr;

       DWORD dwTime;

       char cData[REQ_DATASIZE];

}ECHOREQUEST, *PECHOREQUEST;

typedef struct _ECHOREPLY

{

       IPHDR    ipHdr;

       ECHOREQUEST   echoRequest;

       char    cFiller[256];

}ECHOREPLY, *PECHOREPLY;

u_short checksum(u_short *buffer, int len)

{

       register int nleft = len;

       register u_short *w = buffer;

       register u_short answer;

       register int sum = 0;

       while( nleft > 1 )  {

              sum += *w++;

              nleft -= 2;

       }

       if( nleft == 1 ) {

              u_short    u = 0;

              *(u_char *)(&u) = *(u_char *)w ;

              sum += u;

       }

     sum = (sum >> 16) + (sum & 0xffff);  /* add hi 16 to low 16 */

       sum += (sum >> 16);                   /* add carry */

       answer = ~sum;                           /* truncate to 16 bits */

       return (answer);

}

int SendEchoRequest(SOCKET s,struct sockaddr_in *lpstToAddr)

{

       static ECHOREQUEST echoReq;

       static nId = 1;

       static nSeq = 1;

       int nRet;

       echoReq.icmpHdr.Type         = ICMP_ECHOREQ;

       echoReq.icmpHdr.Code         = 0;

       echoReq.icmpHdr.Checksum = 0;

       echoReq.icmpHdr.ID                   = nId++;

       echoReq.icmpHdr.Seq                  = nSeq++;

       for (nRet = 0; nRet < REQ_DATASIZE; nRet++)

              echoReq.cData[nRet] = ' '+nRet;

       echoReq.dwTime = GetTickCount();

       echoReq.icmpHdr.Checksum = checksum((u_short *)&echoReq, sizeof(ECHOREQUEST));

                                                         

       nRet = sendto(s,

                             (LPSTR)&echoReq,

                             sizeof(ECHOREQUEST),

                             0,

                             (struct sockaddr*)lpstToAddr,

                             sizeof(SOCKADDR_IN));

       if (nRet == SOCKET_ERROR)

       {

              printf("sendto() error:%d\n",WSAGetLastError());

       }

       return (nRet);

}

DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)

{

       ECHOREPLY echoReply;

       int nRet;

       int nAddrLen = sizeof(struct sockaddr_in);

       nRet = recvfrom(s,

                                   (LPSTR)&echoReply,

                                   sizeof(ECHOREPLY),

                                   0,

                                   (LPSOCKADDR)lpsaFrom,

                                   &nAddrLen); 

       if (nRet == SOCKET_ERROR)

       {

              printf("recvfrom() error:%d\n",WSAGetLastError());

       }

       *pTTL = echoReply.ipHdr.TTL;

       return(echoReply.echoRequest.dwTime);          

}

int WaitForEchoReply(SOCKET s)

{

       struct timeval timeout;

       fd_set readfds;

       readfds.fd_count = 1;

       readfds.fd_array[0] = s;

       timeout.tv_sec = 5;

    timeout.tv_usec = 0;

       return(select(1, &readfds, NULL, NULL, &timeout));

}

void Ping(char *pstrHost)

{

       SOCKET   rawSocket;

       LPHOSTENT lpHost;

       struct    sockaddr_in destIP;

       struct    sockaddr_in srcIP;

       DWORD   dwTimeSent;

       DWORD   dwElapsed;

       u_char    cTTL;

       int       nLoop;

       int       nRet;

       rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

       if (rawSocket == SOCKET_ERROR)

       {

              printf("socket() error:%d\n",WSAGetLastError());

              return;

       }

      

       lpHost = gethostbyname(pstrHost);

       if (lpHost == NULL)

       {

              printf("Host not found: %s\n", pstrHost);

              return;

       }

      

       destIP.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));

       destIP.sin_family = AF_INET;

       destIP.sin_port = 0;

       printf("\nPinging %s with %d bytes of data:\n",

                            inet_ntoa(destIP.sin_addr),

                            REQ_DATASIZE);

       for (nLoop = 0; nLoop < 4; nLoop++)

       {

              SendEchoRequest(rawSocket, &destIP);

              nRet = WaitForEchoReply(rawSocket);

              if (nRet == SOCKET_ERROR)

              {

                     printf("select() error:%d\n",WSAGetLastError());

                     break;

              }

              if (!nRet)

              {

                     printf("\nRequest time out");

                     break;

              }

              dwTimeSent = RecvEchoReply(rawSocket, &srcIP, &cTTL);

              dwElapsed = GetTickCount() - dwTimeSent;

              printf("\nReply from %s: bytes=%d time=%ldms TTL=%d",

               inet_ntoa(srcIP.sin_addr),

                        REQ_DATASIZE,

               dwElapsed,

               cTTL);

       }

       printf("\n");

       nRet = closesocket(rawSocket);

       if (nRet == SOCKET_ERROR)

       {

              printf("closesocket() error:%d\n",WSAGetLastError());

       }

}

void main(int argc, char **argv)

{

    WSADATA wsd;

    int nRet;

    if (argc != 2)

    {

              printf("\nUsage: ping hostname\n");

              return;

    }

       if (WSAStartup(MAKEWORD(1,1), &wsd) != 0)

    {

        printf("加载Winsock失败!\n");

    }

       Ping(argv[1]);

       WSACleanup();

}

相关推荐