home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedWinsock.Cab / F112772_XcdPing.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-25  |  8.0 KB  |  286 lines

  1. /*
  2.  * Xceed Winsock Library Sample: Ping
  3.  * Copyright (c) 2000 Xceed Software Inc.
  4.  *
  5.  * This sample shows how to implement a "ping" application
  6.  * using The Xceed Winsock Library.
  7.  *
  8.  * In particular, it demonstrate:
  9.  *  - Connectionless sockets
  10.  *  - Timeouts
  11.  *  - Using "#import" with the Xceed Winsock Library
  12.  *
  13.  * This file is part of the Xceed Winsock Library Samples.
  14.  * The source code in this file is only intended as a supplement
  15.  * to Xceed Winsock Library's documentation, and is provided "as is", 
  16.  * without warranty of any kind, either expressed or implied.
  17.  *
  18.  */
  19.  
  20. #include "stdafx.h"
  21.  
  22. /*
  23.  * This is the easiest way to use the library in Visual C++
  24.  */
  25.  
  26. #pragma warning( disable : 4786 )
  27. #import "XceedWsl.dll" no_namespace named_guids
  28. #pragma warning( default : 4786 )
  29.  
  30. #include "XcdPing.h"
  31.  
  32. /*
  33.  * Function prototypes
  34.  */
  35.  
  36. IXWSocketPtr GetRawICMPSocket( void );
  37. IXWAddressInfoPtr GetRemoteAddress( _bstr_t bstrHostName );
  38. u_short in_cksum(u_short *addr, int len);
  39.  
  40. /*
  41.  * main : This is the entry point of the application
  42.  */
  43.  
  44. int main(int argc, char* argv[])
  45. {
  46.   printf( "Xceed Winsock Library Sample - Ping\n" );
  47.   printf( "-----------------------------------\n" );
  48.  
  49.   if( argc < 2 )
  50.   {
  51.     printf( "Usage: %s hostname [count]\n\n", argv[ 0 ] );
  52.     return 0;
  53.   }
  54.  
  55.   CoInitializeEx( NULL, COINIT_MULTITHREADED );
  56.  
  57.   try
  58.   {
  59.     // Create the connectionless socket and the remote address we need.
  60.     IXWAddressInfoPtr piRemoteAddress = GetRemoteAddress( argv[ 1 ] );
  61.     IXWSocketPtr      piSocket        = GetRawICMPSocket();
  62.  
  63.     // Get a string representation of this address
  64.     WCHAR* pwszRemoteAddress = NULL;
  65.  
  66.     piRemoteAddress->GetAddressString( &pwszRemoteAddress );
  67.  
  68.     printf( "Pinging %s [%S] with %d bytes of data:\n\n", 
  69.             argv[ 1 ], pwszRemoteAddress, REQ_DATASIZE );
  70.  
  71.     CoTaskMemFree( pwszRemoteAddress );
  72.  
  73.     // Set the receive timeout to prevent waiting too long for lost packets
  74.     IXWTransferTimeOutPtr piTimeOut = piSocket;
  75.     piTimeOut->SetReceiveTimeOut( 1000 );
  76.     piTimeOut.Release();
  77.  
  78.     IXWAddressedByteTransferPtr piTransfer = piSocket;
  79.  
  80.     int nCount = ( argc >= 3 ) ? atoi( argv[ 2 ] ) : PING_COUNT;
  81.  
  82.     for( int i = 0; i < nCount; i++ )
  83.     {
  84.       // Build the packet that we send to the ping server
  85.       SEchoRequest xRequest;
  86.  
  87.       xRequest.xIcmpHeader.cType = ICMP_ECHOREQ;
  88.       xRequest.xIcmpHeader.cCode = 0;
  89.       xRequest.xIcmpHeader.wChecksum = 0;
  90.       xRequest.xIcmpHeader.wID = i + 1;
  91.       xRequest.xIcmpHeader.wSeq = i + 1;
  92.  
  93.       for( int j = 0; j < REQ_DATASIZE; j++ )
  94.         xRequest.cData[ j ] = ' ' + j;
  95.  
  96.       xRequest.dwTime = GetTickCount();
  97.  
  98.       xRequest.xIcmpHeader.wChecksum = in_cksum( reinterpret_cast< WORD* >( &xRequest ), sizeof( SEchoRequest ) );
  99.  
  100.       // Send this structure as an array of bytes
  101.       piTransfer->SendBytesTo( piRemoteAddress, sizeof( SEchoRequest ), 
  102.                                reinterpret_cast< BYTE* >( &xRequest ), wsoNone );
  103.  
  104.       // Try to receive answer
  105.       IXWAddressInfoPtr piReceiveAddress;
  106.       DWORD dwReceivedSize = 0;
  107.       BYTE* pcReceivedData = NULL;
  108.  
  109.       try
  110.       {
  111.         piTransfer->ReceiveBytesFrom( &piReceiveAddress, &dwReceivedSize, &pcReceivedData, wroWaitForData );
  112.       }
  113.       catch( const _com_error& xErr )
  114.       {
  115.         if( xErr.Error() == WSL_E_RECEIVETIMEDOUT )
  116.         {
  117.           printf( "Request timed out.\n" );
  118.           continue;
  119.         }
  120.  
  121.         throw( xErr );
  122.       }
  123.  
  124.       // Display information about he received answer
  125.       DWORD dwReceiveTime = GetTickCount();
  126.  
  127.       if( !dwReceivedSize || !pcReceivedData )
  128.         throw( _bstr_t( L"Got an invalid packet." ) );
  129.  
  130.       if( dwReceivedSize < sizeof( SEchoReply ) )
  131.       {
  132.         CoTaskMemFree( pcReceivedData );
  133.         throw( _bstr_t( L"Got an invalid packet." ) );
  134.       }
  135.  
  136.       SEchoReply xReply;
  137.  
  138.       CopyMemory( &xReply, pcReceivedData, sizeof( SEchoReply ) );
  139.       CoTaskMemFree( pcReceivedData );
  140.  
  141.       WCHAR* pwszReceiveAddress = NULL;
  142.  
  143.       piReceiveAddress->GetAddressString( &pwszReceiveAddress );
  144.  
  145.       printf( "Reply from %S: bytes=%d time=%dms TTL=%d\n", pwszReceiveAddress,
  146.                                                             REQ_DATASIZE, 
  147.                                                             dwReceiveTime - xReply.xEchoRequest.dwTime,
  148.                                                             static_cast< int >( xReply.xIpHeader.cTimeToLive ) );
  149.  
  150.       CoTaskMemFree( pwszReceiveAddress );
  151.  
  152.       // Wait one second between each ping
  153.       Sleep( 1000 );
  154.     }
  155.   }
  156.   catch( const _com_error& xErr )
  157.   {
  158.     printf( "*** COM Error %08X\n%s\n\n", xErr.Error(), 
  159.                                           static_cast< const char* >( xErr.Description() ) );
  160.   }
  161.   catch( const _bstr_t& bstrErr )
  162.   {
  163.     printf( "%s\n\n", static_cast< const char* >( bstrErr ) );
  164.   }
  165.   catch( ... )
  166.   {
  167.     printf( "*** Unhandled exception.\n\n" );
  168.   }
  169.  
  170.   CoUninitialize();
  171.     return 0;
  172. }
  173.  
  174. /*
  175.  * GetRawICMPSocket : Create a socket using the ICMP protocol, with raw data format.
  176.  */
  177.  
  178. IXWSocketPtr GetRawICMPSocket( void )
  179. {
  180.   // Create the ICMP protocol
  181.   IXWProtocolLookupPtr  piProtocolLookup( CLSID_Protocols );
  182.   IXWProtocolInfoPtr    piProtocol;
  183.   
  184.   piProtocolLookup->GetProtocol( wafInet, wstRaw, wptIP_ICMP, &piProtocol );
  185.  
  186.   // Create the connectionless socket
  187.   IXWSocketFactoryPtr piSocketFactory( CLSID_SocketFactory );
  188.   IXWSocketPtr        piSocket;
  189.  
  190.   piSocketFactory->CreateConnectionlessSocket( piProtocol, 0, 
  191.                                                const_cast< GUID* >( &__uuidof( piSocket ) ), 
  192.                                                reinterpret_cast< void** >( &piSocket ) );
  193.  
  194.   return piSocket;
  195. }
  196.  
  197. /*
  198.  * GetRemoteAddress : Create an inet address from a string either
  199.  *                    representing a host name (like www.microsoft.com)
  200.  *                    or dotted inet address (like 192.168.0.200)
  201.  */
  202.  
  203. IXWAddressInfoPtr GetRemoteAddress( _bstr_t bstrHostName )
  204. {
  205.   IXWProvideAddressesPtr  piProvideAddresses( CLSID_AddressManager );
  206.   IXWAddressInfoPtr       piAddress;
  207.  
  208.   // First, try to get the address out of a dotted address string format.
  209.   piProvideAddresses->GetAddress( wafInet, const_cast< GUID* >( &__uuidof( piAddress ) ), 
  210.                                   reinterpret_cast< void** >( &piAddress ) );
  211.  
  212.   try
  213.   {
  214.     piAddress->SetAddressString( bstrHostName );
  215.   }
  216.   catch( const _com_error& xErr )
  217.   {
  218.     if( xErr.Error() != WSL_E_INVALIDADDRESSSTRING )
  219.       throw( xErr );
  220.  
  221.     piAddress.Release();
  222.   }
  223.  
  224.   if( !piAddress.GetInterfacePtr() )
  225.   {
  226.     IXWEnumAddressPtr piEnumAddress;
  227.  
  228.     // If SetAddressStrin failed, try to translate a host name to an address.
  229.     piProvideAddresses->GetAddressesFromHostName( bstrHostName, wnsDNS, &piEnumAddress );
  230.     piEnumAddress->RemoteNext( 1, &piAddress, NULL );
  231.   }
  232.  
  233.   return piAddress;
  234. }
  235.  
  236. //
  237. // Mike Muuss' in_cksum() function
  238. // and his comments from the original
  239. // ping program
  240. //
  241. // * Author -
  242. // *    Mike Muuss
  243. // *    U. S. Army Ballistic Research Laboratory
  244. // *    December, 1983
  245.  
  246. /*
  247.  *            I N _ C K S U M
  248.  *
  249.  * Checksum routine for Internet Protocol family headers (C Version)
  250.  *
  251.  */
  252. u_short in_cksum(u_short *addr, int len)
  253. {
  254.     register int nleft = len;
  255.     register u_short *w = addr;
  256.     register u_short answer;
  257.     register int sum = 0;
  258.  
  259.     /*
  260.      *  Our algorithm is simple, using a 32 bit accumulator (sum),
  261.      *  we add sequential 16 bit words to it, and at the end, fold
  262.      *  back all the carry bits from the top 16 bits into the lower
  263.      *  16 bits.
  264.      */
  265.     while( nleft > 1 )  {
  266.         sum += *w++;
  267.         nleft -= 2;
  268.     }
  269.  
  270.     /* mop up an odd byte, if necessary */
  271.     if( nleft == 1 ) {
  272.         u_short    u = 0;
  273.  
  274.         *(u_char *)(&u) = *(u_char *)w ;
  275.         sum += u;
  276.     }
  277.  
  278.     /*
  279.      * add back carry outs from top 16 bits to low 16 bits
  280.      */
  281.     sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
  282.     sum += (sum >> 16);            /* add carry */
  283.     answer = ~sum;                /* truncate to 16 bits */
  284.     return (answer);
  285. }
  286.