【教师 管理 源码】【杜绝源码泄露】【xml源码设置】gethostbyname 源码

时间:2024-12-27 13:14:24 来源:从哪里可以下qt实例源码 分类:时尚

1.Asynchronous socket error 10061
2.WSAAsyncGetHostByName()的简介
3.c语言ping程序中文注释

gethostbyname 源码

Asynchronous socket error 10061

       æœåŠ¡å™¨é”™è¯¯ï¼Œ

       ç«¯å£æ‰«æçš„问题

       åœ¨å†™ç«¯å£æ‰«ææ—¶ ,如果与某主机特定端口无法通信 ,

       å°±æ­¤ä¸»æœºè€Œè¨€ ,我想应该有以下两种情况 :

        1 。此地址上无任何主机存在

        2 。有主机但被扫描的特定端口不存在 ( 也可能是被 firewall 过滤了 )

       å¦‚何得知某端口一打开

       ç»™ä½ æ¥ä¸ªç®€å•çš„吧!

       procedure TForm1.Timer1Timer(Sender: TObject);

       var

        I : integer;

       begin

        Memo1.Clear;

        for I := 0 to do begin

        ServerSocket1.Close;

        ServerSocket1.Port := I;

        try

        ServerSocket1.Open;

        except

        Memo1.Lines.Add(IntToStr(I) + ' 端口被打开 !');

        end;

        end;

       end;

       å¯¹ä¸èµ· ,我指的是别人机器上的 PORT

       ä½ æ˜¯è¯´ PORT 只能被一个程序打开么 ?

       å¯æ˜¯ ,我用 OICQ 时在打开 没问题呀

       æˆ‘把上面的程序改了一下 ,也可以用的。你就去试图连接对方 ,如果通了 ,说明此端口被打

       å¼€ã€‚

       procedure TForm1.ClientSocket1Connect(Sender: TObject;

        Socket: TCustomWinSocket);

       begin

        Memo1.Lines.Add(' 端口 '+IntToStr(Socket.RemotePort)+' 被打开! ');

       end;

       procedure TForm1.Timer1Timer(Sender: TObject);

       begin

        ClientSocket1.Close;

        ClientSocket1.Port := PortID;

        try

        ClientSocket1.Open;

        except

        end;

        Inc(PortID);

       end;

       procedure TForm1.FormCreate(Sender: TObject);

       begin

        PortID := 1;

       end;

       procedure TForm1.ClientSocket1Error(Sender: TObject;

        Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

        var ErrorCode: Integer);

       begin

        try

        ClientSocket1.Close;

        except

        end;

        Memo2.Lines.add(IntToStr(Socket.remotePort));

       end;

       å•é›ªæ¾ä½ çš„方法我试过了可是抱错 :asynchronous socket error

       --------------------------------------------------------------------------------

       æ¥è‡ª :xueminliu 时间 :-3-3 :: ID:

       è¦åŒºåˆ† tcp 和 udp

       oicq 用 udp 协议 ,connect 没有用 ,但是 tcp 可以这样

       å¦å¤– ,如果你写扫描程序可千万不要这样 ,应该使用别的链接方法 ,否则你的踪迹会被别人

       å‘现 .例如使用 sys 扫描或者 fin 扫描 :

       æˆ‘给你异步 socket 的 api 代码 :

       unit Unit1;

       interface

       uses

        Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

        StdCtrls,WInSock, ExtCtrls;

       const WM_SOCKET=WM_USER+1; //socket 消息

       type

        TForm1 = class(TForm)

        Button1: TButton;

        Edit1: TEdit;

        Panel1: TPanel;

        Memo1: TMemo;

        procedure FormCreate(Sender: TObject);

        procedure FormDestroy(Sender: TObject);

        procedure Button1Click(Sender: TObject);

        procedure Button2Click(Sender: TObject);

        procedure Button3Click(Sender: TObject);

        private

        Sockhd : integer; //socket 句柄

        Serv_Addr : Tsockaddr;// 目标地址

       procedure SockEvent(var msg: Tmessage);message WM_SOCKET; // 处理 cocket 消息

        procedure DspMsg(msg : string); // 显示信息

        { Private declarations }

        public

        { Public declarations }

        end;

       Form1: TForm1;

       implementation

       { $R *.DFM}

       function lookup_hostname(const hostname:string):longint; // 把域名转化成 IP 地址

       var

        RemoteHost : PHostEnt; (* no, don't free it! *)

        ip_address: longint;

       begin

        ip_address:=-1;

        try

        if hostname='' then

        begin (* no host given! *)

        lookup_hostname:=ip_address;

        EXIT;

        end

        else

        begin

        ip_address:=Winsock.Inet_Addr(PChar(hostname)); (* try a xxx.xxx.xxx.xx first *)

        if ip_address=SOCKET_ERROR then begin

        RemoteHost:=Winsock.GetHostByName(PChar(hostname));

        if (RemoteHost=NIL) or (RemoteHost^.h_length<=0) then

        begin

        lookup_hostname:=ip_address;

        EXIT; (* host not found *)

        end

        else

        ip_address:=longint(pointer(RemoteHost^.h_addr_list^)^);

        end;

        end;

        except

        ip_address:=-1;

        end;

        lookup_hostname:=ip_address;

       end;

       procedure TFOrm1.DspMsg(msg: string);

       begin

       memo1.Lines.Add(msg+'...');

       if Memo1.Lines.Count> then Memo1.Lines.Delete(0);

       end;

       procedure TForm1.SockEvent(var msg : tmessage); // 处理 socket 消息

       begin

       case msg.LParam of

        FD_READ: begin // 标识可以读数据 ,当然肯定已经链接上了

        dspmsg(' 可以读取数据 ');

        //do what you want do

        end;

       FD_WRITE: begin

        dspmsg(' 可以发送数据 ');

        //do what you want do

        end;

       FD_ERROR: begin

        dspmsg(' 发生错误 ');

        // 如果你是客户端 ,则应该是连接不上 ,即端口没有开

        end;

       FD_CLOSE: Begin

        dspmsg(' 服务器断开连接 ');

        // 对方关闭连接

        end;

       FD_CONNECT: begin

        dspmsg(' 连结上服务器 ');

        // 表示对方端口开放

        end;

       FD_ACCEPT: begin

        dspmsg(' 接收一个请求 ');

        // 这个消息只有服务端可能出现

        end;

       end;

       end;

       procedure TForm1.FormCreate(Sender: TObject);

       var wsaData:TwsaData;

       begin // 启动 winsock 动态链接库

        if WSAStartup (makeword(2,2), wsaData)<>0 then begin

        messagebox(application.handle,' 无法启动 winsock 动态连接库 !',' 警告 ',MB_OK or MB_APPLMODAL or MB_ICONWARNING);

        Application.Terminate;

        end;

       end;

       procedure TForm1.FormDestroy(Sender: TObject);

       begin // 关闭 dll

       WSACleanup;

       end;

       procedure TForm1.Button1Click(Sender: TObject);

       begin

       Sockhd := socket(AF_INET,SOCK_STREAM,0); // 创建 socket 句柄

       if Sockhd<0 then begin

        messagebox(application.handle,' 无法创建句柄 !',' 警告 ',MB_OK or MB_APPLMODAL or MB_ICONWARNING);

        exit;

       end;

        Serv_addr.sin_addr.s_addr:= lookup_hostname(edit1.Text); // 主机名

        Serv_addr.sin_family := PF_INET;

        Serv_addr.sin_port := htons(); //any port you want to connect

       if WSAAsyncSelect(Sockhd,Form1.handle,WM_SOCKET,FD_ACCEPT or FD_CONNECT or FD_CLOSE or FD_READ or FD_WRITE)=SOCKET_ERROR

        then begin

        messagebox(application.handle,' 无法创建句柄 !',' 警告 ',MB_OK or MB_APPLMODAL or MB_ICONWARNING);

        exit;

        end; // 异步 socket

        connect(sockhd,serv_addr,sizeof(serv_addr)); // 连接 ,结果会在前面的处理函数处理

       end;

       end.

       ç›¸ä¿¡åº”该可以满足你的要求

       è¯·é—®å¦‚何编程区分这两种情况

       æœ€å¥½è¯¦ç»†ä¸€ç‚¹å–” ( 我很笨的 )

       å¦‚果在此地址上无主机存在 ,则发出的数据包得不到回应 ,应用程序会等待超时才

       è®¤ä¸ºè¿žæŽ¥å¤±è´¥ ( 被 firewall 过滤时情况一样 ),若有主机但被扫描的特定端口不存在时 ,

       è¯¥ä¸»æœºä¼šå‘出目的端口不存在的应答

       è‡³äºŽå¦‚何编程实现 ,应该可以由错误码来判断 ,在 OnError 事情中判定 ErrorCode 是多

       å° ,再分别处理 ,ErrorCode 的详情参见 Help

       è¿™ä¹ˆé«˜æ·±çš„问题才 分 ,少了

       ç«¯å£æ‰«æä¸æ˜¯è¿™ä¹ˆç®€å• ,否则大家都做

       é¦–先你扫描人家的端口会留下自己的痕迹 ,系统有日志可以察看

       å› æ­¤æˆ‘们做端口扫描的的时候绝对不会直接连接别人 ,而是通过地层的接口编程

       ä¾‹å¦‚在 TCP 三次握手的第三次放弃 ,对方就不会有日志 ,这称为 sys 扫描

       ç»™å¯¹æ–¹ç«¯å£å‘断开连接的请求称为 fin 扫描 .

       é€šè¿‡è¿™ä¸¤ç§æ‰«ææ–¹å¼éƒ½å¯ä»¥å¾—知对方的端口是否开 ,而且不会留下痕迹 .

       æ€»ä¹‹ç«¯å£æ‰«æé‡Œé¢æœ‰å¾ˆå¤šå­¦é—® ,不是这里可以说清除的

       æ€Žä¹ˆåšå‘€ ,如你所说的话好象要直接调用 socket api?

        我现在首先关心的是我提出的问题 ,如何编程区分这两种情况 :

        1 。此地址上无任何主机存在

        2 。有主机但被扫描的特定端口不存在 ( 也可能是被 firewall 过滤了 )

       è¿˜æœ‰ ,为什么我把 clientsocket 的 onread 里的 errorcode 设为 0 了 ,

        还是常常会出现 delphi 自己的错误消息提示 ,象 , 什么的 ,

        这好象是另外一种 error code,如能把它屏蔽我想就不会出现提示了 .

        是吗?如果是 ,该怎么做呢。

       æœ€åŽ : 如果能给我一个多线程的端口扫描源码 ,我再给 分 ( 真的很穷啊 )

       æˆ‘找到了 help 里的有关说明 ( 是在索引中 Error TCP Event 里找到的 )

       WinSock Error Codes

        The following error codes apply to the WinSock ActiveX Controls.

       Error Code Error Message

        The operation is canceled.

        The requested address is a broadcast address, but flag is not set.

        Invalid argument.

        Socket not bound, invalid address or listen is not invoked prior to accept.

        No more file descriptors are available, accept queue is empty.

        Socket is non-blocking and the specified operation will block.

        A blocking Winsock operation is in progress.

        The operation is completed. No blocking operation is in progress.

        The descriptor is not a socket.

        Destination address is required.

        The datagram is too large to fit into the buffer and is truncated.

        The specified port is the wrong type for this socket.

        Option unknown, or unsupported.

        The specified port is not supported.

        Socket type not supported in this address family.

        Socket is not a type that supports connection oriented service.

        Address Family is not supported.

        Address in use.

        Address is not available from the local machine.

        Network subsystem failed.

        The network cannot be reached from this host at this time.

        Connection has timed out when SO_KEEPALIVE is set.

        Connection is aborted due to timeout or other failure.

        The connection is reset by remote side.

        No buffer space is available.

        Socket is already connected.

        Socket is not connected.

        Socket has been shut down.

        The attempt to connect timed out.

        Connection is forcefully rejected.

        Socket already created for this object.

        Socket has not been created for this object.

        Authoritative answer: Host not found.

        Non-Authoritative answer: Host not found.

        Non-recoverable errors.

        Valid name, no data record of requested type.

       æˆ‘想只要对它进行有关操作就能完全屏蔽 winsocket 错误消息 ( 至少

       èƒ½å±è”½å¾ˆå¤š onerror 里的 errorcode 参数无法屏蔽的消息 )

       æˆ‘终于找到原因所在了

       åœ¨æ‰“å¼€ Socket 时也要捕获异常

        try

        ClientSocket.Open;

        except

        MessageBox(MainForm.Handle,'Error connecting to this address','Connect',MB_ICONEXCLAMATION);

        end;

       åœ¨ OnError 中最后要将 ErrorCode 置为 0

        if ErrorEvent=eeConnect then

        begin

        Socket.Close;

        MessageBox(MainForm.Handle,'Error connecting to this address','Connect',MB_ICONEXCLAMATION);

        end

        else if ErrorEvent=eeSend then

        Socket.Close;

        ErrorCode:=0;

       ä½ å¯èƒ½æ— åšç¬¬ä¸€æ­¥

       è€Œè¿™æ ·ä¹Ÿå¯ä»¥åŒºåˆ†ä½ æ‰€è¯´çš„两种情况

       1 。第二步 OnError 就是此地址上无任何主机存在 ,到超时就触发 OnError 事件

       2 。第一步捕捉到异常就是有主机但被扫描的特定端口不存在

WSAAsyncGetHostByName()的简介

       ç®€è¿°ï¼š

       èŽ·å¾—对应于一个主机名的主机信息.-异步版本.

       #include <winsock.h>

       HANDLE PASCAL FAR WSAAsyncGetHostByName (HWND hWnd,

       unsigned int wMsg,const char FAR * name,char FAR * buf,

       int buflen);

       hWnd 当异步请求完成时,应该接收消息的窗口句柄.

       wMsg 当异步请求完成时,将要接收的消息.

       name 指向主机名的指针.

       buf 接收hostent数据的数据区指针.注意该数据区必须大于hostent结构的大小.这是因为不仅Windows Sockets实现要用该数据区域容纳hostent结构,hostent结构的成员引用的所有数据也要在该区域内.建议用户提供一个MAXGETHOSTSTRUCT字节大小的缓冲区.

       buflen上述数据区的大小.

       æ³¨é‡Šï¼š

       æœ¬å‡½æ•°æ˜¯gethostbyname()的异步版本,是用来获取对应于一个主机名的主机名称和地址信息.Windows Sockets的实现启动该操作后立刻返回调用方,并传回一个异步任务句柄,应用程序可以用它来标识该操作.当操作完成时,结果(若有的话)将会拷贝到调用方提供的缓冲区,同时向应用程序的窗口发一条消息.

       å½“异步操作完成时,应用程序的窗口hWnd接收到消息wMsg. wParam参数包含了初次函数调用时返回的异步任务句柄.lParam的高位包含着错误代码.该代码可以是winsock.h中定义的任何错误.错误代码为0说明异步操作成功.在成功完成的情况下,提供给初始函数调用的缓冲区中包含了一个hostent结构.为存取该结构中的元素,初始的缓冲区指针应置为hostent结构的指针,并一如平常地存取.

       æ³¨æ„è‹¥é”™è¯¯ä»£ç ä¸ºWSAENOBUFS,它说明在初始调用时由buflen指出的缓冲区大小对于容纳所有的结果信息来说太小了.在这种情况下,lParam的低位含有提供所有信息所需的缓冲区大小数值.如果应用程序认为获取的数据不够,它就可以在设置了足够容纳所需信息的缓冲区后,重新调用WSAAsyncGetHostByName().(也就是大于lParam低位提供的大小.)

       é”™è¯¯ä»£ç å’Œç¼“冲区大小应使用WSAGETASYNCERROR和WSAGETASYNCBUFLEN宏从lParam中取出.两个宏定义如下:

       #define WSAGETASYNCERROR(lParam) HIWORD(lParam)

       #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)

       ä½¿ç”¨è¿™äº›å®å¯æœ€å¤§åœ°æé«˜åº”用程序源代码的可移植性.

       è¿”回值:

       è¿”回值指出异步操作是否成功地初启.注意它并不隐含操作本身的成功或失败.

       è‹¥æ“ä½œæˆåŠŸåœ°åˆå¯ï¼ŒWSAAsyncGetHostByName()返回一个HANDLE类型的非0值,作为请求需要的异步任务句柄.该值可在两种方式下使用.它可通过WSACancelAsyncRequest()用来取消该操作.也可通过检查wParam消息参数,以匹配异步操作和完成消息.

       å¦‚果异步操作不能初启,WSAAsyncGetHostByName()返回一个0值,并且可使用WSAGetLastError()来获取错误号.

       è¯„价:

       Windows Sockets的实现使用提供给该函数的缓冲区来构造hostent结构以及该结构成员引用的数据区内容.为避免上述的WSAENOBUFS错误,应用程序应提供一个至少MAXGETHOSTSTRUCT字节大小的缓冲区.

       å…³äºŽWindows Sockets提供者的说明:

       Windows Sockets的实现应保证消息能成功地传给应用程序.如果PostMessage()操作失败,Windows Sockets的实现必须重发该消息-只要窗口存在.

       Windows Sockets的提供者在消息中组织lParam时应使用WSAMAKEASYNCREPLY宏.

c语言ping程序中文注释

       编写自己的一个ping程序,可以说是许多人迈出网络编程的第一步吧!!这个ping程序的源代码经过我的修改和调试,基本上可以取代windows中自带的ping程序. 各个模块后都有我的详细注释和修改日志,希望能够对大家的学习有所帮助!!

       /* 本程序的主要源代码来自MSDN网站, 笔者只是做了一些改进和注释! 另外需要注意的是在Build之前,必须加入ws2_.lib库文件,否则会提示"error LNK:"的错误!*/

       Version 1.1 修改记录:

        <1> 解决了socket阻塞的教师 管理 源码问题,从而能够正确地处理超时的请求!

        <2> 增加了由用户控制发送ICMP包的数目的功能(即命令的第二个参数)

        <3> 增加了对ping结果的统计功能.

       #pragma pack(4)

       #include "winsock2.h"

       #include "stdlib.h"

       #include "stdio.h"

       #define ICMP_ECHO 8

       #define ICMP_ECHOREPLY 0

       #define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)

       /* The IP header */

       typedef struct iphdr {

       unsigned int h_len:4; // length of the header

       unsigned int version:4; // Version of IP

       unsigned char tos; // Type of service

       unsigned short total_len; // total length of the packet

       unsigned short ident; // unique identifier

       unsigned short frag_and_flags; // flags

       unsigned char ttl;

       unsigned char proto; // protocol (TCP, UDP etc)

       unsigned short checksum; // IP checksum

       unsigned int sourceIP;

       unsigned int destIP;

       }IpHeader;

       //

       // ICMP header

       //

       typedef struct icmphdr {

       BYTE i_type;

       BYTE i_code; /* type sub code */

       USHORT i_cksum;

       USHORT i_id;

       USHORT i_seq;

       /* This is not the std header, but we reserve space for time */

       ULONG timestamp;

       }IcmpHeader;

       #define STATUS_FAILED 0xFFFF

       #define DEF_PACKET_SIZE

       #define DEF_PACKET_NUMBER 4 /* 发送数据报的个数 */

       #define MAX_PACKET

       #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))

       #define xfree(p) HeapFree (GetProcessHeap(),0,(p))

       void fill_icmp_data(char *, int);

       USHORT checksum(USHORT *, int);

       int decode_resp(char *,int ,struct sockaddr_in *);

       void Usage(char *progname){

       fprintf(stderr,"Usage:\n");

       fprintf(stderr,"%s [number of packets] [data_size]\n",progname);

       fprintf(stderr,"datasize can be up to 1Kb\n");

       ExitProcess(STATUS_FAILED);

       }

       int main(int argc, char **argv){

       WSADATA wsaData;

       SOCKET sockRaw;

       struct sockaddr_in dest,from;

       struct hostent * hp;

       int bread,datasize,times;

       int fromlen = sizeof(from);

       int timeout = ;

       int statistic = 0; /* 用于统计结果 */

       char *dest_ip;

       char *icmp_data;

       char *recvbuf;

       unsigned int addr=0;

       USHORT seq_no = 0;

       if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0){

       fprintf(stderr,"WSAStartup failed: %d\n",GetLastError());

       ExitProcess(STATUS_FAILED);

       }

       if (argc <2 ) {

       Usage(argv[0]);

       }

       sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);

       //

       //注:为了使用发送接收超时设置(即设置SO_RCVTIMEO, SO_SNDTIMEO),

       // 必须将标志位设为WSA_FLAG_OVERLAPPED !

       //

       if (sockRaw == INVALID_SOCKET) {

       fprintf(stderr,杜绝源码泄露"WSASocket() failed: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,

       sizeof(timeout));

       if(bread == SOCKET_ERROR) {

       fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       timeout = ;

       bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,

       sizeof(timeout));

       if(bread == SOCKET_ERROR) {

       fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       memset(&dest,0,sizeof(dest));

       hp = gethostbyname(argv[1]);

       if (!hp){

       addr = inet_addr(argv[1]);

       }

       if ((!hp) && (addr == INADDR_NONE) ) {

       fprintf(stderr,"Unable to resolve %s\n",argv[1]);

       ExitProcess(STATUS_FAILED);

       }

       if (hp != NULL)

       memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);

       else

       dest.sin_addr.s_addr = addr;

       if (hp)

       dest.sin_family = hp->h_addrtype;

       else

       dest.sin_family = AF_INET;

       dest_ip = inet_ntoa(dest.sin_addr);

       //

       // atoi函数原型是: int atoi( const char *string );

       // The return value is 0 if the input cannot be converted to an integer !

       //

       if(argc>2)

       {

       times=atoi(argv[2]);

       if(times == 0)

        times=DEF_PACKET_NUMBER;

       }

       else

        times=DEF_PACKET_NUMBER;

       if (argc >3)

       {

       datasize = atoi(argv[3]);

        if (datasize == 0)

        datasize = DEF_PACKET_SIZE;

       if (datasize >) /* 用户给出的数据包大小太大 */

       {

        fprintf(stderr,"WARNING : data_size is too large !\n");

        datasize = DEF_PACKET_SIZE;

       }

       }

       else

        datasize = DEF_PACKET_SIZE;

       datasize += sizeof(IcmpHeader);

       icmp_data = (char*)xmalloc(MAX_PACKET);

       recvbuf = (char*)xmalloc(MAX_PACKET);

       if (!icmp_data) {

       fprintf(stderr,"HeapAlloc failed %d\n",GetLastError());

       ExitProcess(STATUS_FAILED);

       }

       memset(icmp_data,0,MAX_PACKET);

       fill_icmp_data(icmp_data,datasize);

       //

       //显示提示信息

       //

       fprintf(stdout,"\nPinging %s ....\n\n",dest_ip);

       for(int i=0;i{

       int bwrote;

       ((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);

       bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));

       if (bwrote == SOCKET_ERROR){

       if (WSAGetLastError() == WSAETIMEDOUT) {

       printf("Request timed out.\n");

       continue;

       }

       fprintf(stderr,"sendto failed: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       if (bwrote < datasize ) {

       fprintf(stdout,"Wrote %d bytes\n",bwrote);

       }

       bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);

       if (bread == SOCKET_ERROR){

       if (WSAGetLastError() == WSAETIMEDOUT) {

       printf("Request timed out.\n");

       continue;

       }

       fprintf(stderr,"recvfrom failed: %d\n",WSAGetLastError());

       ExitProcess(STATUS_FAILED);

       }

       if(!decode_resp(recvbuf,bread,&from))

       statistic++; /* 成功接收的数目++ */

       Sleep();

       }

       /

*

       Display the statistic result

       */

       fprintf(stdout,"\nPing statistics for %s \n",dest_ip);

       fprintf(stdout," Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)\n",times,

        statistic,(times-statistic),(float)(times-statistic)/times*);

       WSACleanup();

       return 0;

       }

       /*

       The response is an IP packet. We must decode the IP header to locate

       the ICMP data

       */

       int decode_resp(char *buf, int bytes,struct sockaddr_in *from) {

       IpHeader *iphdr;

       IcmpHeader *icmphdr;

       unsigned short iphdrlen;

       iphdr = (IpHeader *)buf;

       iphdrlen = (iphdr->h_len) * 4 ; // number of -bit words *4 = bytes

       if (bytes < iphdrlen + ICMP_MIN) {

       printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));

       }

       icmphdr = (IcmpHeader*)(buf + iphdrlen);

       if (icmphdr->i_type != ICMP_ECHOREPLY) {

       fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type);

       return 1;

       }

       if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) {

       fprintf(stderr,"someone else''s packet!\n");

       return 1;

       }

       printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));

       printf(" icmp_seq = %d. ",icmphdr->i_seq);

       printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);

       printf("\n");

       return 0;

       }

       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 >> ) + (cksum & 0xffff);

       cksum += (cksum >>);

       return (USHORT)(~cksum);

       }

       /*

       Helper function to fill in various stuff in our ICMP request.

       */

       void fill_icmp_data(char * icmp_data, int datasize){

       IcmpHeader *icmp_hdr;

       char *datapart;

       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);

       //

       // Place some junk in the buffer.

       //

       memset(datapart,''E'', datasize - sizeof(IcmpHeader));

       }

       /