BCAST.C
资源名称:bcast.zip [点击查看]
上传用户:zhuguiling
上传日期:2007-01-07
资源大小:9k
文件大小:26k
源码类别:
网络编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright 1996-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- /*
- Module Name:
- bcast.c
- Abstract:
- This module illustrates the Win32 Winsock and Mailslot APIs to do a generic
- broadcast over IPX, UDP and Mailslot protocols.
- This example implements a client and a server. The example has a number of
- command line options. For example,
- -s To run the example as a server(default role).
- -c To run the example as a client.
- -p <i or m or u> To specify the protocol to be used.
- i - IPX.
- m - Mailslots.
- u - UDP(default protocol).
- -e <Endpoint> To specify an end point of your choice. This is a mandatory
- parameter. Servers create this endpoint and read broadcast messages. An
- endpoint in case Mailslot protocol is a Mailslot name.(default is 5005).
- -d <DomainName> - To specify a domain name or a workgroup name. This is
- useful for Mailslot clients, only.
- To run the application as a server, the following command lines can be
- specified:
- bcast -s -e 8000 -p u
- bcast -s -e 8000 -p i
- bcast -s -e MAILSLOT1 -p m
- To run the application as a client, the following command lines can be
- specified:
- bcast -c -e 8000 -p u
- bcast -c -e 8000 -p i
- bcast -c -e MAILSLOT1 -p m -d DOMAIN1
- bcast -c -e MAILSLOT1 -p m -d WORKGROUP1
- Author:
- Rajesh Dadhia (rajeshd) 02-Mar-96
- Revision History:
- */
- #include <stdio.h>
- #include <time.h>
- #include <windows.h>
- #include <winsock.h>
- #include <wsipx.h>
- #include <wsnwlink.h>
- #define MAX_MSGLEN 80
- #define MAX_ADDLEN 80
- #define MAX_MSLOTNAME 80
- typedef enum _MODE { CLIENT=0, SERVER } MODE;
- typedef enum _PROTOCOL { UDP=0, IPX, MAILSLOT } PROTOCOL;
- BOOL __stdcall
- CtrlCHandler (
- DWORD dwEvent
- );
- void __stdcall
- DoMailSlot (
- MODE mRole,
- LPSTR lpsEndPoint,
- LPSTR lpsDomainName
- );
- void __stdcall
- DoIpx (
- MODE mRole,
- USHORT usEndPoint
- );
- void __stdcall
- DoUdp (
- MODE mRole,
- USHORT usEndPoint
- );
- void __stdcall
- DoMailSlotServer (
- LPSTR lpsEndPoint
- );
- void __stdcall
- DoMailSlotClient (
- LPSTR lpsEndPoint,
- LPSTR lpsDomainName
- );
- void __stdcall
- DoUdpServer (
- USHORT usEndPoint
- );
- void __stdcall
- DoUdpClient (
- USHORT usEndPoint
- );
- void __stdcall
- DoIpxServer (
- USHORT usEndPoint
- );
- void __stdcall
- DoIpxClient (
- USHORT usEndPoint
- );
- void __stdcall
- Usage (
- CHAR *pszProgramName
- );
- void __stdcall
- PrintError (
- LPSTR lpszRoutine,
- LPSTR lpszCallName,
- DWORD dwError
- );
- CHAR * __stdcall
- IpxnetAddr (
- CHAR *lpBuffer,
- CHAR *lpsNetnum,
- CHAR *lpsNodenum
- );
- void __stdcall
- DoStartup ( void );
- void __stdcall
- DoCleanup ( void );
- //
- // Global Variables
- //
- // If Startup was successful, fStarted is used to keep track.
- BOOL fStarted = FALSE;
- // Global socket descriptor
- SOCKET sock = INVALID_SOCKET;
- void __cdecl
- main (
- INT argc,
- CHAR **argv
- )
- {
- // Default role of the application is SERVER, which means receiver of
- // the broadcast messages.
- MODE mRole = SERVER;
- // Deafult protocol used is UDP.
- PROTOCOL pProto = UDP;
- // Default Endpoint.
- USHORT usEndPoint = 5005;
- // Strings pointing to Endpoint and DomainName(necessary for Mailslots).
- LPSTR lpsEndPoint, lpsDomainName;
- INT i;
- CHAR chProto;
- //
- // Install the CTRL+BREAK Handler
- //
- if ( FALSE == SetConsoleCtrlHandler ( (PHANDLER_ROUTINE) CtrlCHandler,
- TRUE
- ) )
- {
- PrintError ( "main", "SetConsoleCtrlHandler", GetLastError ( ) );
- }
- //
- // allow the user to override settings with command line switches
- //
- for ( i = 1; i < argc; i++ )
- {
- if ( ( *argv[i] == '-' ) || ( *argv[i] == '/' ) )
- {
- switch ( tolower ( *( argv[i]+1 ) ) )
- {
- //
- // Role of the application (Client - Sender of broadcasts).
- //
- case 'c':
- mRole = CLIENT;
- break;
- //
- // Role of the application (Server - Receiver of broadcasts)
- //
- case 's':
- mRole = SERVER;
- break;
- //
- // Network protocol (Mailslots, IPX or UDP).
- //
- case 'p':
- chProto = tolower ( *argv[++i] );
- if ( 'm' == chProto )
- {
- pProto = MAILSLOT;
- }
- else if ( 'i' == chProto )
- {
- pProto = IPX;
- }
- else
- pProto = UDP;
- break;
- //
- // EndPoint.
- //
- case 'e':
- lpsEndPoint = argv[++i];
- break;
- //
- // DomainName (Important for Mailslot broadcasts, only).
- //
- case 'd':
- lpsDomainName = argv[++i];
- break;
- //
- // Help.
- //
- case 'h':
- case '?':
- default:
- Usage ( argv[0] );
- }
- }
- else
- //
- // Help.
- //
- Usage ( argv[0] );
- }
- //
- // If the protocol specified is not MAILSLOT, convert the endpoint
- // information to integer format from the string format.
- //
- if ( MAILSLOT != pProto )
- {
- usEndPoint = atoi ( lpsEndPoint );
- }
- //
- // Print a Summary of the switches specfied
- // Helpful for debugging
- //
- fprintf ( stdout, "SUMMARY:n" );
- fprintf ( stdout, "tRole-> %sn", (CLIENT == mRole)?"Client":"Server" );
- fprintf ( stdout, "tProtocol-> %sn",
- ( MAILSLOT == pProto ) ? "MAILSLOT" :
- ( IPX == pProto ) ? "IPX" : "UDP" );
- fprintf ( stdout, "tEndpoint-> %sn", lpsEndPoint );
- //
- // Check the protocol specified.
- // Call the appropriate handler rouine. By default the protocol
- // is UDP.
- //
- switch ( pProto )
- {
- case MAILSLOT :
- DoMailSlot ( mRole, lpsEndPoint, lpsDomainName );
- break;
- case IPX:
- DoStartup ( );
- DoIpx ( mRole, usEndPoint );
- break;
- default:
- DoStartup ( );
- DoUdp ( mRole, usEndPoint );
- break;
- }
- return;
- }
- //
- // CtrlCHandler () intercepts the CTRL+BREAK or CTRL+C events and calls the
- // cleanup routines.
- //
- BOOL __stdcall
- CtrlCHandler (
- DWORD dwEvent
- )
- {
- if ( ( CTRL_C_EVENT == dwEvent ) || ( CTRL_BREAK_EVENT == dwEvent ) )
- {
- DoCleanup ( );
- }
- return FALSE;
- }
- //
- // DoMailSlot () function calls appropriate handler function (client/server),
- // if protocol=MAILSLOT is specified. By default, the role of the application
- // is - SERVER.
- //
- void __stdcall
- DoMailSlot (
- MODE mRole,
- LPSTR lpsEndPoint,
- LPSTR lpsDomainName
- )
- {
- switch ( mRole )
- {
- case CLIENT:
- DoMailSlotClient ( lpsEndPoint, lpsDomainName );
- break;
- default:
- DoMailSlotServer ( lpsEndPoint );
- }
- return;
- }
- //
- // DoIpx () function calls appropriate handler function (client/server),
- // if protocol=IPX is specified. By default, the role of the application
- // is - SERVER.
- //
- void __stdcall
- DoIpx (
- MODE mRole,
- USHORT usEndPoint
- )
- {
- //
- // Initialize the global socket descriptor.
- //
- sock = socket ( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );
- if ( INVALID_SOCKET == sock )
- {
- PrintError( "DoIpx", "socket", WSAGetLastError ( ) );
- }
- switch ( mRole )
- {
- case CLIENT:
- DoIpxClient ( usEndPoint );
- break;
- default:
- DoIpxServer ( usEndPoint );
- }
- return;
- }
- //
- // DoUdp () function calls appropriate handler function (client/server),
- // if protocol=UDP is specified. By default, the role of the application
- // is - SERVER.
- //
- void __stdcall
- DoUdp (
- MODE mRole,
- USHORT usEndPoint
- )
- {
- //
- // Initialize the global socket descriptor.
- //
- sock = socket ( AF_INET, SOCK_DGRAM, 0 );
- if ( INVALID_SOCKET == sock)
- {
- PrintError ( "DoUdp", "socket", WSAGetLastError() );
- }
- switch ( mRole )
- {
- case CLIENT:
- DoUdpClient ( usEndPoint );
- break;
- default:
- DoUdpServer ( usEndPoint );
- }
- return;
- }
- //
- // DoMailSlotServer () function receives a mailslot message on a particular
- // mailslot. The function creates a mailslot, posts a ReadFile () to receive
- // the message. The function then checks the first four bytes of the message
- // for the message ID, and discards all the messages with same ID, in future.
- //
- void __stdcall
- DoMailSlotServer (
- LPSTR lpsEndPoint
- )
- {
- HANDLE hSlot;
- // Variables that store MessageID, previous messageID, number of bytes to
- // read/read, size of next available message and the number of messages.
- DWORD dwMessageID,
- dwPrevID,
- cbMessage,
- cbRead,
- cbToRead,
- nMessages;
- BOOL fResult;
- CHAR achMailSlotName[MAX_MSLOTNAME],
- achBuffer[MAX_MSGLEN + sizeof ( DWORD )];
- // Variable that points past the message ID part in the message.
- LPSTR lpsMessage;
- //
- // Create a string for the mailslot name.
- //
- wsprintf ( achMailSlotName, "\\.\mailslot\%s", lpsEndPoint );
- //
- // Create the mailslot.
- //
- hSlot = CreateMailslot ( achMailSlotName,
- 0,
- MAILSLOT_WAIT_FOREVER,
- (LPSECURITY_ATTRIBUTES) NULL
- );
- if ( INVALID_HANDLE_VALUE == hSlot )
- {
- PrintError ( "DoMailSlotServer", "CreateMailSlot", GetLastError() );
- }
- //
- // Post ReadFile() and read a message.
- //
- cbToRead = MAX_MSGLEN + sizeof (DWORD);
- fResult = ReadFile ( hSlot,
- achBuffer,
- cbToRead,
- &cbRead,
- (LPOVERLAPPED) NULL
- );
- if ( TRUE != fResult )
- {
- PrintError ( "DoMailSlotServer", "ReadFile", GetLastError() );
- }
- achBuffer[cbRead] = ' ';
- //
- // Get the message ID part from the message.
- //
- memcpy ( &dwMessageID, achBuffer, sizeof ( DWORD ) );
- //
- // Adjust the actual message pointer.
- //
- lpsMessage = achBuffer + sizeof ( DWORD );
- //
- // Print the message
- //
- fprintf ( stdout,
- "A MailSlot Message of %d bytes received with ID %dn",
- strlen (lpsMessage ),
- dwMessageID
- );
- fprintf ( stdout, "MessageText->%sn", lpsMessage );
- //
- // Check for duplicate messages.
- //
- dwPrevID = dwMessageID;
- while ( 1 )
- {
- //
- // get information on pending messages.
- //
- fResult = GetMailslotInfo ( hSlot,
- (LPDWORD) NULL,
- &cbMessage,
- &nMessages,
- (LPDWORD) NULL
- );
- if ( TRUE != fResult )
- {
- PrintError ( "DoMailSlotServer",
- "GetMailSlotInfo",
- GetLastError ( )
- );
- }
- //
- // Break if no more messages.
- //
- if ( MAILSLOT_NO_MESSAGE == cbMessage )
- break;
- //
- // We now know how much to read.
- //
- cbToRead = cbMessage;
- fResult = ReadFile ( hSlot,
- achBuffer,
- cbToRead,
- &cbRead,
- (LPOVERLAPPED) NULL
- );
- if ( TRUE != fResult )
- {
- PrintError ( "DoMailSlotServer",
- "ReadFile",
- GetLastError ( )
- );
- }
- achBuffer[cbRead] = ' ';
- memcpy ( &dwMessageID, achBuffer, sizeof (DWORD) );
- //
- // print the message only if it is not a duplicate.
- //
- lpsMessage = achBuffer + sizeof (DWORD);
- if ( dwMessageID != dwPrevID )
- {
- fprintf ( stdout,
- "A MailSlot Message of %d bytes received with ID %dn",
- strlen (lpsMessage ),
- dwMessageID
- );
- fprintf ( stdout, "MessageText->%sn", achBuffer );
- }
- dwPrevID = dwMessageID;
- }
- //
- // Close the handle to our mailslot.
- //
- fResult = CloseHandle ( hSlot );
- if ( TRUE != fResult )
- {
- PrintError ( "DoMailSlotServer", "CloseHandle", GetLastError() );
- }
- return;
- }
- //
- // DoMailSlotClient () function implements the broadcast routine for a
- // Mailslot client. The function opens handle to the mailslot using
- // CreateFile (). CreateFile will fail on Windows NT for local mailslots,
- // if the mailslot is not already created using CreateMailSlot () API.
- //
- // The function appends a message number to the message which the server uses
- // to discard duplicate messages. In the event of a client runnig on a system
- // with multiple transport protocols loaded, a mailsot message is sent over
- // each protocol.
- //
- // This routine broadcasts a mailslot message to everyone on a Windows NT
- // domain, it can also be used to send a mailslot message to a particular
- // host or a workgroup.
- //
- void __stdcall
- DoMailSlotClient (
- LPSTR lpsEndPoint,
- LPSTR lpsDomainName
- )
- {
- HANDLE hFile;
- // Variables that store MessageID, number of bytes to write/written.
- DWORD dwMessageID,
- cbWritten,
- cbToWrite;
- BOOL fResult;
- CHAR achMailSlotName[MAX_MSLOTNAME],
- achBuffer[MAX_MSGLEN + sizeof ( DWORD ) ];
- if ( NULL == lpsDomainName )
- {
- fprintf ( stdout,
- "Domain/Workgroup name must be specified....Exitingn"
- );
- exit ( 1 );
- }
- //
- // Create a string for the mailslot name.
- //
- wsprintf ( achMailSlotName,
- "\\%s\mailslot\%s",
- lpsDomainName,
- lpsEndPoint
- );
- //
- // Open a handle to the mailslot.
- //
- hFile = CreateFile ( achMailSlotName,
- GENERIC_WRITE,
- FILE_SHARE_READ,
- (LPSECURITY_ATTRIBUTES) NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- (HANDLE) NULL
- );
- if ( INVALID_HANDLE_VALUE == hFile)
- {
- PrintError ( "DoMailSlotClient", "CreateFile", GetLastError ( ) );
- }
- //
- // Generate a Message ID.
- //
- srand ( (UINT) time ( NULL) );
- dwMessageID = rand ( );
- memcpy ( achBuffer, &dwMessageID, sizeof ( DWORD ) );
- lstrcpy ( achBuffer + sizeof (DWORD), "A MailSlot Broadcast Message" );
- //
- // Total number of bytes to write.
- //
- cbToWrite = sizeof ( DWORD ) + strlen ( achBuffer + sizeof ( DWORD ) );
- //
- // Send a mailslot message.
- //
- fResult = WriteFile ( hFile,
- achBuffer,
- cbToWrite,
- &cbWritten,
- (LPOVERLAPPED) NULL
- );
- if ( TRUE != fResult )
- {
- PrintError ( "DoMailSlotClient", "WriteFile", GetLastError ( ) );
- }
- fprintf ( stdout,
- "%d bytes of MailSlot data broadcasted with ID %dn",
- cbWritten,
- dwMessageID
- );
- //
- // Close the mailslot handle.
- //
- fResult = CloseHandle ( hFile );
- if ( TRUE != fResult )
- {
- PrintError ( "DoMailSlotClient", "CloseHandle", GetLastError() );
- }
- return;
- }
- //
- // DoUdpServer () function receives the broadcast on a specified port. The
- // server will have to post a recv (), before the client sends the broadcast.
- //
- void __stdcall
- DoUdpServer (
- USHORT usEndPoint
- )
- {
- // IP address structures needed to bind to a local port and get the sender's
- // information.
- SOCKADDR_IN saUdpServ, saUdpCli;
- INT err, nSize;
- CHAR achBuffer[MAX_MSGLEN];
- //
- // bind to the specified port.
- //
- saUdpServ.sin_family = AF_INET;
- saUdpServ.sin_addr.s_addr = htonl ( INADDR_ANY );
- saUdpServ.sin_port = htons ( usEndPoint );
- err = bind ( sock, (SOCKADDR FAR *)&saUdpServ, sizeof ( SOCKADDR_IN ) );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoUdpServer", "bind", WSAGetLastError ( ) );
- }
- //
- // receive a datagram on the bound port number.
- //
- nSize = sizeof ( SOCKADDR_IN );
- err = recvfrom ( sock,
- achBuffer,
- MAX_MSGLEN,
- 0,
- (SOCKADDR FAR *) &saUdpCli,
- &nSize
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoUdpServer", "recvfrom", WSAGetLastError ( ) );
- }
- //
- // print the sender's information.
- //
- achBuffer[err] = ' ';
- fprintf ( stdout, "A Udp Datagram of length %d bytes received from ", err );
- fprintf ( stdout, "ntIP Adress->%s ", inet_ntoa ( saUdpCli.sin_addr ) );
- fprintf ( stdout, "ntPort Number->%dn", ntohs ( saUdpCli.sin_port ) );
- fprintf ( stdout, "MessageText->%sn", achBuffer );
- //
- // Call the cleanup routine
- //
- DoCleanup ( );
- return;
- }
- //
- // DoUdpClient () function implements the broadcast routine for an UDP
- // client. The function sets the SO_BROADCAST option with the global socket.
- // Calling this API is important. After binding to a local port, it sends an
- // UDP boradcasts to the IP address INADDR_BROADCAST, with a particular
- // port number.
- //
- void __stdcall
- DoUdpClient (
- USHORT usEndPoint
- )
- {
- // IP address structures needed to fill the source and destination
- // addresses.
- SOCKADDR_IN saUdpServ, saUdpCli;
- INT err;
- CHAR achMessage[MAX_MSGLEN];
- // Variable to set the broadcast option with setsockopt ().
- BOOL fBroadcast = TRUE;
- err = setsockopt ( sock,
- SOL_SOCKET,
- SO_BROADCAST,
- (CHAR *) &fBroadcast,
- sizeof ( BOOL )
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoUdpClient", "setsockopt", WSAGetLastError ( ) );
- }
- //
- // bind to a local socket and an interface.
- //
- saUdpCli.sin_family = AF_INET;
- saUdpCli.sin_addr.s_addr = htonl ( INADDR_ANY );
- saUdpCli.sin_port = htons ( 0 );
- err = bind ( sock, (SOCKADDR *) &saUdpCli, sizeof (SOCKADDR_IN) );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoUdpClient", "bind", WSAGetLastError ( ) );
- }
- //
- // Fill an IP address structure, to send an IP broadcast. The
- // packet will be broadcasted to the specified port.
- //
- saUdpServ.sin_family = AF_INET;
- saUdpServ.sin_addr.s_addr = htonl ( INADDR_BROADCAST );
- saUdpServ.sin_port = htons ( usEndPoint );
- lstrcpy ( achMessage, "A Broadcast Datagram" );
- err = sendto ( sock,
- achMessage,
- lstrlen ( achMessage ),
- 0,
- (SOCKADDR *) &saUdpServ,
- sizeof ( SOCKADDR_IN )
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoUdpClient", "sendto", WSAGetLastError ( ) );
- }
- fprintf ( stdout, "%d bytes of data broadcastedn", err );
- //
- // Call the cleanup routine.
- //
- DoCleanup ( );
- return;
- }
- //
- // DoIpxServer () function receives the broadcast on a specified socket. The
- // server will have to post a recv (), before the client sends the broadcast.
- // It is necessary call setsockopt () with SO_BROADCAST flag set, in order to
- // receive IPX broadcasts on Windows 95.
- //
- void __stdcall
- DoIpxServer (
- USHORT usEndPoint
- )
- {
- // IPX address structures needed to bind to a local socket and get the
- // sender's information.
- SOCKADDR_IPX saIpxServ, saIpxCli;
- INT err, nSize;
- CHAR achBuffer[MAX_MSGLEN],
- achAddress[MAX_ADDLEN];
- OSVERSIONINFO osVer;
- // Variable to set the broadcast option with setsockopt ().
- BOOL fResult, fBroadcast = TRUE;
- //
- // Check the platform.
- //
- osVer.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
- fResult = GetVersionEx ( &osVer);
- if ( FALSE == fResult)
- {
- PrintError ( "DoIpxServer", "GetVersionEx", GetLastError ( ) );
- }
- //
- // If the platform is Windows 95, call setsockopt ().
- //
- if ( VER_PLATFORM_WIN32_WINDOWS == osVer.dwPlatformId )
- {
- err = setsockopt ( sock,
- SOL_SOCKET,
- SO_BROADCAST,
- (CHAR *) &fBroadcast,
- sizeof ( BOOL )
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoIpxServer", "setsockopt", WSAGetLastError() );
- }
- }
- //
- // bind to the specified socket.
- //
- saIpxServ.sa_family = AF_IPX;
- saIpxServ.sa_socket = usEndPoint;
- memset ( saIpxServ.sa_netnum, 0, sizeof (saIpxServ.sa_netnum ) );
- memset ( saIpxServ.sa_nodenum, 0, sizeof (saIpxServ.sa_nodenum ) );
- err = bind ( sock, (SOCKADDR *) &saIpxServ, sizeof (SOCKADDR_IPX) );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoIpxServer", "bind", WSAGetLastError ( ) );
- }
- //
- // receive a datagram on the bound socket number.
- //
- nSize = sizeof ( SOCKADDR_IPX );
- err = recvfrom ( sock,
- achBuffer,
- MAX_MSGLEN,
- 0,
- (SOCKADDR *) &saIpxCli,
- &nSize
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoIpxServer", "recvfrom", WSAGetLastError ( ) );
- }
- //
- // print the sender's information.
- //
- achBuffer[err] = ' ';
- fprintf ( stdout,
- "An Ipx Datagram of length %d bytes received from ",
- err );
- fprintf ( stdout,
- "ntIPX Adress->%s ",
- IpxnetAddr ( achAddress,
- saIpxCli.sa_netnum,
- saIpxCli.sa_nodenum
- )
- );
- fprintf ( stdout, "ntSocket Number->%dn", saIpxCli.sa_socket );
- fprintf ( stdout, "MessageText->%sn", achBuffer );
- //
- // Call the cleanup routine.
- //
- DoCleanup ( );
- return;
- }
- //
- // DoIpxClient () function implements the broadcast routine for a an IPX
- // client. The fucntion sets the SO_BROADCAST option with the gloabal socket.
- // Calling this API is important. After binding to a local port, it sends an IPX
- // packet to the address with node number as all 1's and net number as all 0's,
- // with a particuler socket number.
- //
- void __stdcall
- DoIpxClient (
- USHORT usEndPoint
- )
- {
- // IPX address structures needed to fill the source and destination
- // addresses.
- SOCKADDR_IPX saIpxServ, saIpxCli;
- INT err;
- CHAR achMessage[MAX_MSGLEN];
- // Variable to set the broadcast option with setsockopt ().
- BOOL fBroadcast = TRUE;
- err = setsockopt ( sock,
- SOL_SOCKET,
- SO_BROADCAST,
- (CHAR *) &fBroadcast,
- sizeof ( BOOL )
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoIpxClient", "setsockopt", WSAGetLastError ( ) );
- }
- //
- // bind to a local socket and an interface.
- //
- saIpxCli.sa_family = AF_IPX;
- saIpxCli.sa_socket = (USHORT) 0;
- memset ( saIpxCli.sa_netnum, 0, sizeof ( saIpxCli.sa_netnum ) );
- memset ( saIpxCli.sa_nodenum, 0, sizeof ( saIpxCli.sa_nodenum ) );
- err = bind ( sock, (SOCKADDR *) &saIpxCli, sizeof ( SOCKADDR_IPX ) );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoIpxClient", "bind", WSAGetLastError() );
- }
- //
- // Fill an IPX address structure, to send an IPX broadcast. The
- // packet will be broadcasted to the specified socket.
- //
- saIpxServ.sa_family = AF_IPX;
- saIpxServ.sa_socket = usEndPoint;
- memset ( saIpxServ.sa_netnum, 0, sizeof ( saIpxServ.sa_netnum ) );
- memset ( saIpxServ.sa_nodenum, 0xFF, sizeof ( saIpxServ.sa_nodenum ) );
- lstrcpy ( achMessage, "A Broadcast Datagram" );
- err = sendto ( sock,
- achMessage,
- lstrlen ( achMessage ),
- 0,
- (SOCKADDR *) &saIpxServ,
- sizeof ( SOCKADDR_IPX )
- );
- if ( SOCKET_ERROR == err )
- {
- PrintError ( "DoIpxClient", "sendto", WSAGetLastError ( ) );
- }
- fprintf ( stdout, "%d bytes of data broadcastedn", err);
- //
- // Call the cleanup routine.
- //
- DoCleanup ( );
- return;
- }
- //
- // Usage () lists the available command line options.
- //
- void __stdcall
- Usage (
- CHAR *pszProgramName
- )
- {
- fprintf ( stderr, "Usage: %sn", pszProgramName );
- fprintf ( stderr,
- "t-s or -c (s - server, c - client, default - server)n" );
- fprintf ( stderr,
- "t-p <i or m or u> (i - IPX, m - Mailslots, u - UDP)n" );
- fprintf ( stderr, "t-e <Endpoint>n" );
- fprintf ( stderr,
- "t-d <DomainName> - needed only for a Mailslot clientn" );
- fprintf ( stderr,
- "ntDefault Values-> Role:Server, Protocol:UDP, EndPoint:5005n" );
- exit ( 1 );
- }
- //
- // PrintError () is a function available globally for printing the error and
- // doing the cleanup.
- //
- void __stdcall
- PrintError (
- LPSTR lpszRoutine,
- LPSTR lpszCallName,
- DWORD dwError
- )
- {
- fprintf ( stderr,
- "The Call to %s() in routine() %s failed with error %dn",
- lpszCallName,
- lpszRoutine,
- dwError
- );
- DoCleanup ( );
- exit ( 1 );
- }
- //
- // IpxnetAddr () function converts an IPX address address in the binary form
- // to ascii format, it fills the input buffer with the address and returns a
- // pointer to it.
- //
- CHAR * __stdcall
- IpxnetAddr (
- CHAR *lpBuffer,
- CHAR *lpsNetnum,
- CHAR *lpsNodenum
- )
- {
- wsprintf ( lpBuffer,
- "%02X%02X%02X%02X.%02X%02X%02X%02X%02X%02X",
- (UCHAR) lpsNetnum[0], (UCHAR) lpsNetnum[1],
- (UCHAR) lpsNetnum[2], (UCHAR) lpsNetnum[3],
- (UCHAR) lpsNodenum[0], (UCHAR) lpsNodenum[1],
- (UCHAR) lpsNodenum[2], (UCHAR) lpsNodenum[3],
- (UCHAR) lpsNodenum[4], (USHORT) lpsNodenum[5]
- );
- return ( lpBuffer);
- }
- //
- // DoStartup () initializes the Winsock DLL with Winsock version 1.1
- //
- void __stdcall
- DoStartup ( void )
- {
- WSADATA wsaData;
- INT iRetVal;
- iRetVal = WSAStartup ( MAKEWORD ( 1,1 ), &wsaData );
- if ( 0 != iRetVal)
- {
- PrintError ( "DoStartup", "WSAStartup", iRetVal );
- }
- //
- // Set the global flag.
- //
- fStarted = TRUE;
- return;
- }
- //
- // DoCleanup () will close the global socket which was opened successfully by
- // a call to socket (). Additionally, it will call WSACleanup (), if a call
- // to WSAStartup () was made successfully.
- //
- void __stdcall
- DoCleanup ( void )
- {
- if ( INVALID_SOCKET != sock )
- {
- closesocket ( sock );
- }
- if ( TRUE == fStarted )
- {
- WSACleanup ( );
- }
- fprintf ( stdout, "DONEn" );
- return;
- }