home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedWinsock.Cab / F112740_Chat.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-27  |  6.8 KB  |  222 lines

  1. /*
  2.  * Xceed Winsock Library Sample: Chat connectionless
  3.  * Copyright (c) 2000 Xceed Software Inc.
  4.  *
  5.  * This is a standard chat console application using connectionless 
  6.  * sockets to broadcast over the network to find available chat clients.
  7.  *
  8.  * In particular, it demonstrate:
  9.  *  - The ConnectionlessSocket class
  10.  *  - Broadcasting
  11.  *  - Using "#import" with the Xceed Winsock Library
  12.  *  - Using ATL to help implement event interfaces
  13.  *
  14.  * This file is part of the Xceed Winsock Library Samples.
  15.  * The source code in this file is only intended as a supplement
  16.  * to Xceed Winsock Library's documentation, and is provided "as is", 
  17.  * without warranty of any kind, either expressed or implied.
  18.  *
  19.  */
  20.  
  21. #include "stdafx.h"
  22. #include <stdio.h>
  23. #include <conio.h>
  24. #include "Chat.h"
  25.  
  26. /*
  27.  * Run: This is the entry point of the application and the heart of this 
  28.  *      console application.
  29.  */
  30. void CChat::Run( void )
  31. {
  32.   printf( "The Xceed Winsock Library - Connectionless Chat Sample\n" );
  33.   printf( "------------------------------------------------------\n" );
  34.   printf( "Enter \"quit\" to quit this application\n" );
  35.  
  36.   do
  37.   {
  38.     char  szLine[ 200 ];
  39.     gets( szLine );
  40.  
  41.     if( lstrcmpi( szLine, "quit" ) == 0 )
  42.     {
  43.       break;
  44.     }
  45.     else
  46.     {
  47.       // Broadcast this string, including the null-term char.
  48.       DWORD dwSize  = lstrlen( szLine ) + 1;
  49.  
  50.       // m_piSocket is a smart pointer. See CreateSocket.
  51.       try
  52.       {
  53.         m_piSocket->SendBytesTo( IXWAddressInfoPtr( m_piBroadcastAddress ), 
  54.                                  dwSize, 
  55.                                  ( BYTE* )szLine, 
  56.                                  wsoNone );
  57.       }
  58.       catch( const _com_error& xErr )
  59.       {
  60.         printf( "***** COM Error %08X\n%s\n\n", xErr.Error(), 
  61.                                                 static_cast< const char* >( xErr.Description() ) );
  62.       }
  63.       catch( ... )
  64.       {
  65.         printf( "***** Unhandled exception.\n\n" );
  66.       }
  67.     }
  68.   } while( true );
  69. }
  70.  
  71. /*
  72.  * CreateSocket: Create an instance of a connectionless socket, and bind 
  73.  *               it to the correct address.
  74.  */
  75.  
  76. HRESULT CChat::CreateSocket( void )
  77. {
  78.   // Since we are using smart pointers created by the #import directive
  79.   // we do not need to check return codes. Instead, these smart pointers
  80.   // throw exceptions when an error occurs.
  81.  
  82.   try
  83.   {
  84.     // First, we must create the desired protocol object, using 
  85.     // the protocol collection.
  86.     IXWProtocolLookupPtr  piLookup( CLSID_Protocols );
  87.     IXWProtocolInfoPtr    piProtocol;
  88.  
  89.     piLookup->GetProtocol( wafInet, wstUnspecified, wptIP_UDP, &piProtocol );
  90.  
  91.     // Then we must create our connectionless socket, using the socket factory
  92.     IXWSocketFactoryPtr piFactory( CLSID_SocketFactory );
  93.  
  94.     piFactory->CreateConnectionlessSocket( piProtocol, 0, 
  95.                                            ( GUID* )&IID_IXWAddressedByteTransfer, 
  96.                                            ( void** )&m_piSocket );
  97.  
  98.     // This sample is broadcasting throughtout the local network.
  99.     // Let's make sure this socket is ready for broadcasting.
  100.     IXWSocketPtr  piSocket = m_piSocket;
  101.  
  102.     piSocket->SetBroadcastEnabled( TRUE );
  103.  
  104.     // To broadcast with an IP protocol, we need a special broadcast
  105.     // address. Instead of requiring intimate knowledge of the format,
  106.     // why not just ask the AddressManager about that!!!
  107.     IXWProvideAddressesPtr  piProvide( CLSID_AddressManager );
  108.  
  109.     try
  110.     {
  111.       piProvide->GetBroadcastAddress( wafInet, ( GUID* )&IID_IXWInetAddressInfo, ( void** )&m_piBroadcastAddress );
  112.     }
  113.     catch( ... )
  114.     {
  115.       // No broadcast address available on this machine (probably a Win9x machines).
  116.       // So we use 255.255.255.255 directly.
  117.       m_piBroadcastAddress.CreateInstance( CLSID_InetAddress );
  118.       m_piBroadcastAddress->SetAddress( 0xffffffff ); // 255.255.255.255
  119.     }
  120.  
  121.     m_piBroadcastAddress->SetPort( 5180 );
  122.  
  123.     // We want to automatically be informed everytime data arrives. So we
  124.     // advise for the OnAddressedBytesReceived event
  125.     IXWAdviseAddressedByteTransferEventsPtr piAdvise = m_piSocket;
  126.  
  127.     piAdvise->AddressedByteTransferAdvise( IXWAddressedByteTransferEventsPtr( this ), 
  128.                                            wtaAdviseReceivedAlways,
  129.                                            &m_dwCookie );
  130.  
  131.     // Finally, we want to bind this socket to a specific custom UDP port.
  132.     // To achieve this, we create an Inet address, and leave the Address field to zero.
  133.     // This represents "any local address".
  134.     IXWInetAddressInfoPtr piAddress( CLSID_InetAddress );
  135.  
  136.     piAddress->SetPort( 5180 );
  137.     piSocket->SetLocalAddress( IXWAddressInfoPtr( piAddress ) );
  138.   }
  139.   catch( const _com_error& xErr )
  140.   {
  141.     printf( "***** COM Error %08X\n%s\n\n", xErr.Error(), 
  142.                                             static_cast< const char* >( xErr.Description() ) );
  143.   }
  144.   catch( ... )
  145.   {
  146.     printf( "***** Unhandled exception.\n\n" );
  147.   }
  148.  
  149.   return S_OK;
  150. }
  151.  
  152. /*
  153.  * OnAddressedBytesSent: We do not need to do anything special in this event
  154.  */
  155. HRESULT __stdcall CChat::raw_OnAddressedBytesSent (
  156.     struct IXWAddressedByteTransfer * piTransfer,
  157.     struct IXWAddressInfo * piRemoteAddress,
  158.     unsigned long dwBytesSent,
  159.     unsigned long dwUserParam,
  160.     HRESULT hResultCode )
  161. {
  162.   return S_OK;
  163. }
  164.  
  165. /*
  166.  * OnAddressedBytesReceived: This event is triggered everytime data is received
  167.  *                           by the library for this socket.
  168.  */
  169. HRESULT __stdcall CChat::raw_OnAddressedBytesReceived (
  170.     struct IXWAddressedByteTransfer * piTransfer,
  171.     struct IXWAddressInfo * piRemoteAddress,
  172.     unsigned long * pdwBytesReceived,
  173.     unsigned char * * ppcData,
  174.     unsigned long dwUserParam,
  175.     HRESULT hResultCode )
  176. {
  177.   // Let's get a string representing the remote address
  178.   _bstr_t sMessage;
  179.   WCHAR*  pwszAddress;
  180.  
  181.   HRESULT hr = piRemoteAddress->GetAddressString( &pwszAddress );
  182.  
  183.   if( FAILED( hr ) )
  184.   {
  185.     printf( "[Unknown address] >" );
  186.   }
  187.   else
  188.   {
  189.     printf( "[%S] >", pwszAddress );
  190.     CoTaskMemFree( pwszAddress );
  191.   }
  192.  
  193.   if( *pdwBytesReceived )
  194.   {
  195.     // The data should be null-terminated
  196.     printf( "%s\n", *ppcData );
  197.   }
  198.   else
  199.   {
  200.     printf( "*** EMPTY ***\n" );
  201.   }
  202.  
  203.   // The library would free all this for us, but it gives us the chance to
  204.   // save all this data a trip back the call chain.
  205.   CoTaskMemFree( *ppcData );
  206.   *ppcData  = NULL;
  207.   *pdwBytesReceived = 0;
  208.  
  209.   return S_OK;
  210. }
  211.  
  212. /*
  213.  * OnAddressedBytesAvailable: We do not need to do anything special in this event
  214.  */
  215. HRESULT __stdcall CChat::raw_OnAddressedBytesAvailable (
  216.     struct IXWAddressedByteTransfer * piTransfer,
  217.     unsigned long dwBytesReceived,
  218.     unsigned long dwBytesAvailable )
  219. {
  220.   return S_OK;
  221. }
  222.