Ping 操作

咱也来个 ping 函数,使用的主要是 ICMP(Internet Control Message Protocol) 提供的函数来完成的,用到了下面几个结构:

  1. #define WSADESCRIPTION_LEN  256
  2. #define WSASYS_STATUS_LEN   128
  3. typedef struct WSAData {
  4.   WORD wVersion;
  5.   WORD wHighVersion;
  6.   char szDescription[WSADESCRIPTION_LEN+1];
  7.   char szSystemStatus[WSASYS_STATUS_LEN+1];
  8.   unsigned short iMaxSockets;
  9.   unsigned short iMaxUdpDg;
  10.   char FAR* lpVendorInfo;
  11. } WSADATA;
  12. typedef struct icmp_echo_reply {
  13.   IPAddr Address;
  14.   ULONG Status;
  15.   ULONG RoundTripTime;
  16.   USHORT DataSize;
  17.   USHORT Reserved;
  18.   PVOID Data;
  19.   struct ip_option_information Options;
  20. } ICMP_ECHO_REPLY;
  21. typedef struct ip_option_information {
  22.   UCHAR Ttl;
  23.   UCHAR Tos;
  24.   UCHAR Flags;
  25.   UCHAR OptionsSize;
  26.   PUCHAR OptionsData;
  27. } IP_OPTION_INFORMATION;
  28. typedef struct hostent {
  29.   char FAR* h_name;
  30.   char FAR FAR** h_aliases;
  31.   short h_addrtype;
  32.   short h_length;
  33.   char FAR FAR** h_addr_list;
  34. } HOSTENT;

已改为类结构来实现,提供了三个公用方法:
1. Ping( tcAddress, tiTimeout )  - 第一个参数为要 ping 测试的网址或其 IP 地址,第二个参数【可选】为等待回应的时间(ms)。返回 Ping 操作是否成功
2. GetResult - 如果 Ping 操作成功,用它来检索结果信息
3. GetErrMsg - 如果 Ping 操作失败,用它来检索出错信息

下面是示例代码:

  1. m.oPing = NEWOBJECT( 'ping' )
  2. IF m.oPing.ping( INPUTBOX( '网址或 IP 地址:''Ping 测试''www.csdn.net' ))
  3.   MESSAGEBOX( m.oPing.GetResult(), 64, '结果' )
  4. ELSE
  5.   MESSAGEBOX( m.oPing.GetErrMsg(), 16, 'Error' )
  6. ENDIF
  7. DEFINE CLASS ping AS custom
  8.   HIDDEN errmsg
  9.   errmsg = ''
  10.   HIDDEN echoinfo
  11.   echoinfo = ''
  12.   Name = 'ping'
  13.   PROCEDURE Ping
  14.     LPARAMETERS tcIpAddress, tiTimeout
  15.     IF ( PCOUNT() < 2 ) OR ( 'N' != VARTYPE( m.tiTimeout )) OR ( m.tiTimeout < 0 )
  16.       m.tiTimeout = 500
  17.     ENDIF
  18.     LOCAL lSuccess
  19.     IF This.StartWSA()
  20.       m.lSuccess = This._ping( ALLTRIM( m.tcIpAddress ), m.tiTimeout )
  21.       WSACleanup()
  22.     ELSE
  23.       m.lSuccess = .F.
  24.     ENDIF
  25.     
  26.     RETURN m.lSuccess
  27.   ENDPROC
  28.   HIDDEN PROCEDURE api_decl
  29.     DECLARE Long IcmpCreateFile IN icmp
  30.     DECLARE Long IcmpCloseHandle IN icmp Long IcmpHandle
  31.     DECLARE Long IcmpSendEcho IN icmp ;
  32.       Long IcmpHandle, Long DestAddr, ;
  33.       String RequestData, Long RequestSize, Long RequestOpts, ;
  34.       String @ ReplyBuff, Long ReplySize, Long nTimeout
  35.     DECLARE Long WSAGetLastError IN ws2_32
  36.     DECLARE Long WSAStartup IN ws2_32 ;
  37.       Long wVersionRequired, String @ lpWSADATA
  38.     DECLARE Long WSACleanup IN ws2_32
  39.     DECLARE Long gethostbyname IN ws2_32 String szHost
  40.     DECLARE Long inet_addr IN ws2_32 String szIpAddr
  41.     DECLARE Long GetLastError IN WIN32API
  42.     DECLARE Long GetIpErrorString IN Iphlpapi ;
  43.       Long ErrorCode, String @ Buffer, Long @ Size
  44.     DECLARE Long FormatMessage IN WIN32API ;
  45.       Long dwFlags, Long lpSource, Long dwMessageId, Long dwLanguageId, ;
  46.       String @ lpBuffer, Long nSize, Long Arguments
  47.   ENDPROC
  48.   HIDDEN PROCEDURE _ping
  49.     LPARAMETERS tcAddress, tiTimeout
  50.     LOCAL cTag, iAddress, hPort, lSuccess, cEcho, iErrNo
  51.     m.lSuccess = .F.
  52.     m.cTag = m.tcAddress
  53.     IF ISALPHA( m.cTag )
  54.       m.tcAddress = This.GetIpAddress( m.cTag )
  55.       m.cTag = m.cTag + ' [ ' + m.tcAddress + ' ] '
  56.     ENDIF
  57.     m.iAddress = inet_addr( m.tcAddress )
  58.     IF INLIST( m.iAddress, 0, -1 )
  59.       This.ErrMsg = '无效的地址。'
  60.     ELSE
  61.       m.hPort = IcmpCreateFile()
  62.       IF ( 0 == m.hPort )
  63.         This.ErrMsg = This.win32msg( GetLastError())
  64.       ELSE
  65.         m.cEcho = REPLICATE( CHR(0), 0x100 )
  66.         IF ( 0 == IcmpSendEcho( m.hPort, m.iAddress, 'pingtest', 8, ;
  67.           0, @ m.cEcho, 0x100, m.tiTimeout ))
  68.           m.iErrNo = GetLastError()
  69.           This.ErrMsg = This._GetErrMsg( m.iErrNo )
  70.         ELSE
  71.           m.lSuccess = .T.
  72.           TEXT TO This.EchoInfo NOSHOW TEXTMERGE
  73. Ping:<<CHR(9)>><<m.cTag>>
  74. 时间:<<CHR(9)>><<CTOBIN( SUBSTR( m.cEcho, 9, 4 ), 'rs' )>> ms
  75. TTL:<<CHR(9)>><<CTOBIN( SUBSTR( m.cEcho, 21, 1 )+CHR(0), '2rs' )>>
  76.           ENDTEXT
  77.         ENDIF
  78.         IcmpCloseHandle( m.hPort )
  79.       ENDIF
  80.     ENDIF
  81.     RETURN m.lSuccess
  82.   ENDPROC
  83.   HIDDEN PROCEDURE win32msg
  84.     LPARAMETERS tiErrNo
  85.     #define FORMAT_MESSAGE_FROM_SYSTEM      0x1000
  86.     #define FORMAT_MESSAGE_IGNORE_INSERTS   0x0200
  87.     #define FORMAT_MESSAGE_MAX_WIDTH_MASK   0x000000FF
  88.     #define LANG_USER_DEFAULT               0x0804
  89.     LOCAL cBuffer, iLen
  90.     m.cBuffer = REPLICATE( CHR(0), 256+1 )
  91.     m.iLen = FormatMessage( ;
  92.         FORMAT_MESSAGE_FROM_SYSTEM ;
  93.       + FORMAT_MESSAGE_MAX_WIDTH_MASK ;
  94.       + FORMAT_MESSAGE_IGNORE_INSERTS, ;
  95.       0, m.tiErrNo, ;
  96.       LANG_USER_DEFAULT, ;
  97.       @ m.cBuffer, 256, 0 )
  98.     RETURN LEFT( m.cBuffer, m.iLen )
  99.   ENDPROC
  100.   PROCEDURE GetErrMsg
  101.     RETURN This.ErrMsg
  102.   ENDPROC
  103.   PROCEDURE GetResult
  104.     RETURN This.EchoInfo
  105.   ENDPROC
  106.   HIDDEN PROCEDURE _GetErrMsg
  107.     LPARAMETERS tiErrNo
  108.     LOCAL iSize, cMsg
  109.     m.iSize = 255
  110.     m.cMsg = REPLICATE( CHR(0), m.iSize )
  111.     IF ( 0 == GetIpErrorString( m.tiErrNo, @ m.cMsg, @ m.iSize ))
  112.       RETURN STRCONV( LEFT( m.cMsg, m.iSize ), 6 )
  113.     ELSE
  114.       RETURN This.win32msg( m.tiErrNo )
  115.     ENDIF
  116.   ENDPROC
  117.   HIDDEN PROCEDURE GetIpAddress
  118.     LPARAMETERS tcHostName
  119.     LOCAL pHostEnt, cAddr, cRet, ii
  120.     m.pHostEnt = gethostbyname( m.tcHostName )
  121.     IF ( 0 == m.pHostEnt )
  122.       This.ErrMsg = This._GetErrMsg( WSAGetLastError())
  123.       RETURN ''
  124.     ENDIF
  125.     m.pHostEnt = CTOBIN( SYS( 2600, m.pHostEnt+12, 4 ), 'rs' )
  126.     m.pHostEnt = CTOBIN( SYS( 2600, m.pHostEnt, 4 ), 'rs' )
  127.     m.cAddr = SYS( 2600, m.pHostEnt, 4 )
  128.     m.cRet = ''
  129.     FOR m.ii = 1 TO 4
  130.       m.cRet = m.cRet + '.' + TRANSFORM( ASC( SUBSTR( m.cAddr, m.ii, 1 )))
  131.     ENDFOR
  132.     RETURN SUBSTR( m.cRet, 2 )
  133.     ENDPROC
  134.   HIDDEN PROCEDURE StartWSA
  135.     #define WS_VERSION_REQD     0x0101
  136.     LOCAL lSuccess, cWSAD
  137.     m.cWSAD = REPLICATE( CHR(0), 402 )      && 402 = 2+2+256+1+128+1+4*3
  138.     m.lSuccess = .F.
  139.     IF ( 0 == WSAStartup( WS_VERSION_REQD, @ m.cWSAD ))
  140.       IF ( WS_VERSION_REQD == CTOBIN(SUBSTR( m.cWSAD, 1, 2 ), '2rs' ) )
  141.         m.lSuccess = .T.
  142.       ELSE
  143.         WSACleanup()
  144.         This.ErrMsg = '需要支持 1.1 版的 WinSock。'
  145.       ENDIF
  146.     ELSE
  147.       This.ErrMsg = '初始化 WinSock 失败。'
  148.     ENDIF
  149.     RETURN ( m.lSuccess )
  150.     ENDPROC
  151.   PROCEDURE Init
  152.     This.api_decl()
  153.   ENDPROC
  154. ENDDEFINE

代码长了点,主要是错误处理用了不少代码

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值