WIN32汇编语言教程:第16章 TCP/IP和网络通信 · 16.5 ICMP协议编程(5)

              mov    @stTimeval.tv_sec,0

               mov    @stTimeval.tv_usec,1000000 ;超时时间1秒

              invoke select,0,addr @stFdSet,NULL,NULL,addr @stTimeval

              .if    eax == SOCKET_ERROR

                      invoke _ConsolePrint,addr szErrSocket

                    .continue

              .endif

              .if    eax

;********************************************************************

; 接收返回数据包

;********************************************************************

                     mov    @dwSize,sizeof @stFrom

                      invoke recvfrom,@hSocket,addr szBigBuffer,\

                             sizeof szBigBuffer,0,addr @stFrom,addr @dwSize

                      .if    eax == SOCKET_ERROR

                              invoke _ConsolePrint,addr szErrSocket

                     .else

                     mov    eax,@stFrom.sin_addr

                      .if    eax != @stDest.sin_addr

                             jmp    @B

                      .endif

                     mov    bx,word ptr szBigBuffer+\

                             sizeof ip_hdr+icmp_hdr.icmp_id

                     mov    cx,word ptr szBigBuffer+\

                             sizeof ip_hdr+icmp_hdr.icmp_seq

                     .if    bx != @dwID || cx != @dwSeq

                             jmp    @B

                     .endif

;********************************************************************

; 如果返回的数据包是由目标主机所发的话,则显示时间和 TTL 数据

;********************************************************************

                      invoke inet_ntoa,eax

                      .if    eax != NULL

                             invoke lstrcpy,addr @szBuffer,eax

                      .endif

                     invoke GetTickCount

                      sub    eax,dword ptr szBigBuffer+\

                              sizeof ip_hdr+icmp_hdr.icmp_data

                     movzx  ecx,szBigBuffer + ip_hdr.ip_ttl

                     invoke wsprintf,addr szBuffer,addr szReply,\

                             addr @szBuffer,PACKET_SIZE,eax,ecx

                              invoke _ConsolePrint,addr szBuffer

                      .endif

              .else

                      invoke _ConsolePrint,addr szErrTimeout

             .endif

              inc    @dwID

              inc    @dwSeq

              invoke Sleep,1000

      .endw

      invoke closesocket,@hSocket

_Ping_Ret:

      popad

      ret

 

_Ping        endp

;####################################################################

start:

              call      _ConsoleInit

             invoke _argc

              .if    eax == 2

                      invoke WSAStartup,101h,addr stWsa

                      .if    ! eax

                             invoke _argv,1,addr szHostName,\

                                      sizeof szHostName

                              invoke _HostnameToIP,addr szHostName

                             .if    eax

                                      invoke _Ping,eax

                             .endif

                      .endif

                      invoke WSACleanup

             .else

                      invoke _ConsolePrint,addr szHelp

              .endif

             invoke ExitProcess,NULL

;####################################################################

              end    start

程序首先调用_ConsoleInit子程序来获取控制台窗口的输入输出句柄,然后通过_CmdLine.asm中的_argc函数获取参数的数量,如果参数不等于2,说明用户没有输入参数或者输入了太多的参数,那么程序在显示帮助信息后直接退出。

如果输入了合适的参数,程序使用_argv子程序将参数取出并存放到szHostName变量中,然后用_HostnameToIP子程序将输入的主机名或者字符串格式的IP地址串转换成32位的IP地址,最后调用_Ping子程序来完成ICMP数据包的收发工作。

1. 主机名到IP地址的解析

Ping程序既可以将主机名当做参数输入,也可以输入IP地址字符串,比如在命令行中输入ping www.sina.com.cn的时候,程序的运行结果是:

The host [www.sina.com.cn] has 5 IP addresses:

202.106.185.203 / 202.106.185.198 / 202.106.185.196 / 202.106.185.205 /

202.106.185.204

Ping first IP 202.106.185.203 with 32 bytes of data:

 

Reply from 202.106.185.203: bytes=32 time=40ms TTL=244

Reply from 202.106.185.203: bytes=32 time=30ms TTL=244

Reply from 202.106.185.203: bytes=32 time=50ms TTL=244

Reply from 202.106.185.203: bytes=32 time=40ms TTL=244

而输入ping 202.106.185.204命令的时候,运行结果是:

Ping 202.106.185.204 with 32 bytes of data:

 

Reply from 202.106.185.204: bytes=32 time=40ms TTL=244

Reply from 202.106.185.204: bytes=32 time=40ms TTL=244

Reply from 202.106.185.204: bytes=32 time=30ms TTL=244

Reply from 202.106.185.204: bytes=32 time=40ms TTL=244

在第一个使用示范中,_HostnameToIP子程序将www.sina.com.cn解析成了5个IP地址,那么如何对主机名进行解析呢?

在_HostnameToIP子程序的一开始,首先使用inet_addr函数尝试对输入的字符串进行转换,如果输入的是“aa.bb.cc.dd”类型的IP地址字符串,那么函数将返回正确的IP地址,如果返回值是INADDR_NONE的话,说明输入的不是合法的IP地址字符串,程序则将这个字符串当做主机名来进行解析。

将主机名解析到IP地址使用gethostbyname函数:

   invoke gethostbyname,lphostname

   .if    eax

           ;处理返回的数据

   .endif

函数惟一的输入参数是需要解析的主机名字符串,如果解析失败将返回0,否则函数返回一个指针,指向位于WinSock接口内部缓冲区中的一个hostent结构中,这个结构的定义是:

hostent STRUCT

 h_name   DWORD  ?        ;指针,指向和IP地址对应的主机名

 h_alias  DWORD  ?        ;指针,指向一个包含别名指针的列表

 h_addr   WORD   ?        ;返回的IP地址类型

 h_len    WORD   ?        ;每个地址的长度

 h_list   DWORD  ?        ;指向一个指针列表

hostent ENDS

上页:第16章 TCP/IP和网络通信 · 16.5 ICMP协议编程(4) 下页:第16章 TCP/IP和网络通信 · 16.5 ICMP协议编程(6)

第16章 TCP/IP和网络通信

版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号