home *** CD-ROM | disk | FTP | other *** search
- /*
- * Xceed Winsock Library Sample: Chat connectionless
- * Copyright (c) 2000 Xceed Software Inc.
- *
- * This is a standard chat console application using connectionless
- * sockets to broadcast over the network to find available chat clients.
- *
- * In particular, it demonstrate:
- * - The ConnectionlessSocket class
- * - Broadcasting
- * - Using "#import" with the Xceed Winsock Library
- * - Using ATL to help implement event interfaces
- *
- * This file is part of the Xceed Winsock Library Samples.
- * The source code in this file is only intended as a supplement
- * to Xceed Winsock Library's documentation, and is provided "as is",
- * without warranty of any kind, either expressed or implied.
- *
- */
-
- #include "stdafx.h"
- #include <stdio.h>
- #include <conio.h>
- #include "Chat.h"
-
- /*
- * Run: This is the entry point of the application and the heart of this
- * console application.
- */
- void CChat::Run( void )
- {
- printf( "The Xceed Winsock Library - Connectionless Chat Sample\n" );
- printf( "------------------------------------------------------\n" );
- printf( "Enter \"quit\" to quit this application\n" );
-
- do
- {
- char szLine[ 200 ];
- gets( szLine );
-
- if( lstrcmpi( szLine, "quit" ) == 0 )
- {
- break;
- }
- else
- {
- // Broadcast this string, including the null-term char.
- DWORD dwSize = lstrlen( szLine ) + 1;
-
- // m_piSocket is a smart pointer. See CreateSocket.
- try
- {
- m_piSocket->SendBytesTo( IXWAddressInfoPtr( m_piBroadcastAddress ),
- dwSize,
- ( BYTE* )szLine,
- wsoNone );
- }
- catch( const _com_error& xErr )
- {
- printf( "***** COM Error %08X\n%s\n\n", xErr.Error(),
- static_cast< const char* >( xErr.Description() ) );
- }
- catch( ... )
- {
- printf( "***** Unhandled exception.\n\n" );
- }
- }
- } while( true );
- }
-
- /*
- * CreateSocket: Create an instance of a connectionless socket, and bind
- * it to the correct address.
- */
-
- HRESULT CChat::CreateSocket( void )
- {
- // Since we are using smart pointers created by the #import directive
- // we do not need to check return codes. Instead, these smart pointers
- // throw exceptions when an error occurs.
-
- try
- {
- // First, we must create the desired protocol object, using
- // the protocol collection.
- IXWProtocolLookupPtr piLookup( CLSID_Protocols );
- IXWProtocolInfoPtr piProtocol;
-
- piLookup->GetProtocol( wafInet, wstUnspecified, wptIP_UDP, &piProtocol );
-
- // Then we must create our connectionless socket, using the socket factory
- IXWSocketFactoryPtr piFactory( CLSID_SocketFactory );
-
- piFactory->CreateConnectionlessSocket( piProtocol, 0,
- ( GUID* )&IID_IXWAddressedByteTransfer,
- ( void** )&m_piSocket );
-
- // This sample is broadcasting throughtout the local network.
- // Let's make sure this socket is ready for broadcasting.
- IXWSocketPtr piSocket = m_piSocket;
-
- piSocket->SetBroadcastEnabled( TRUE );
-
- // To broadcast with an IP protocol, we need a special broadcast
- // address. Instead of requiring intimate knowledge of the format,
- // why not just ask the AddressManager about that!!!
- IXWProvideAddressesPtr piProvide( CLSID_AddressManager );
-
- try
- {
- piProvide->GetBroadcastAddress( wafInet, ( GUID* )&IID_IXWInetAddressInfo, ( void** )&m_piBroadcastAddress );
- }
- catch( ... )
- {
- // No broadcast address available on this machine (probably a Win9x machines).
- // So we use 255.255.255.255 directly.
- m_piBroadcastAddress.CreateInstance( CLSID_InetAddress );
- m_piBroadcastAddress->SetAddress( 0xffffffff ); // 255.255.255.255
- }
-
- m_piBroadcastAddress->SetPort( 5180 );
-
- // We want to automatically be informed everytime data arrives. So we
- // advise for the OnAddressedBytesReceived event
- IXWAdviseAddressedByteTransferEventsPtr piAdvise = m_piSocket;
-
- piAdvise->AddressedByteTransferAdvise( IXWAddressedByteTransferEventsPtr( this ),
- wtaAdviseReceivedAlways,
- &m_dwCookie );
-
- // Finally, we want to bind this socket to a specific custom UDP port.
- // To achieve this, we create an Inet address, and leave the Address field to zero.
- // This represents "any local address".
- IXWInetAddressInfoPtr piAddress( CLSID_InetAddress );
-
- piAddress->SetPort( 5180 );
- piSocket->SetLocalAddress( IXWAddressInfoPtr( piAddress ) );
- }
- catch( const _com_error& xErr )
- {
- printf( "***** COM Error %08X\n%s\n\n", xErr.Error(),
- static_cast< const char* >( xErr.Description() ) );
- }
- catch( ... )
- {
- printf( "***** Unhandled exception.\n\n" );
- }
-
- return S_OK;
- }
-
- /*
- * OnAddressedBytesSent: We do not need to do anything special in this event
- */
- HRESULT __stdcall CChat::raw_OnAddressedBytesSent (
- struct IXWAddressedByteTransfer * piTransfer,
- struct IXWAddressInfo * piRemoteAddress,
- unsigned long dwBytesSent,
- unsigned long dwUserParam,
- HRESULT hResultCode )
- {
- return S_OK;
- }
-
- /*
- * OnAddressedBytesReceived: This event is triggered everytime data is received
- * by the library for this socket.
- */
- HRESULT __stdcall CChat::raw_OnAddressedBytesReceived (
- struct IXWAddressedByteTransfer * piTransfer,
- struct IXWAddressInfo * piRemoteAddress,
- unsigned long * pdwBytesReceived,
- unsigned char * * ppcData,
- unsigned long dwUserParam,
- HRESULT hResultCode )
- {
- // Let's get a string representing the remote address
- _bstr_t sMessage;
- WCHAR* pwszAddress;
-
- HRESULT hr = piRemoteAddress->GetAddressString( &pwszAddress );
-
- if( FAILED( hr ) )
- {
- printf( "[Unknown address] >" );
- }
- else
- {
- printf( "[%S] >", pwszAddress );
- CoTaskMemFree( pwszAddress );
- }
-
- if( *pdwBytesReceived )
- {
- // The data should be null-terminated
- printf( "%s\n", *ppcData );
- }
- else
- {
- printf( "*** EMPTY ***\n" );
- }
-
- // The library would free all this for us, but it gives us the chance to
- // save all this data a trip back the call chain.
- CoTaskMemFree( *ppcData );
- *ppcData = NULL;
- *pdwBytesReceived = 0;
-
- return S_OK;
- }
-
- /*
- * OnAddressedBytesAvailable: We do not need to do anything special in this event
- */
- HRESULT __stdcall CChat::raw_OnAddressedBytesAvailable (
- struct IXWAddressedByteTransfer * piTransfer,
- unsigned long dwBytesReceived,
- unsigned long dwBytesAvailable )
- {
- return S_OK;
- }
-