用setsockopt函数,用它可以设置超时,也可以实现广播,具体的可以参考MSDN。

解决方案 »

  1.   

      你说的应该是这个吧 BOOL flag = TRUE;
      ::setsockopt(m_hSocket, SOL_SOCKET, SO_BROADCAST, (char*)&flag, sizeof(BOOL));但我在发送数据的时候SOCKADDR却要填入接收地址。就不能实现向网内所有地址进行了。
      

  2.   

    /*******************************************************************************       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.cAbstract:    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 WORKGROUP1Author:    Rajesh Dadhia (rajeshd) 02-Mar-96Revision 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 80typedef 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-> %s\n", (CLIENT == mRole)?"Client":"Server" );
        fprintf ( stdout, "\tProtocol-> %s\n", 
          ( MAILSLOT == pProto ) ? "MAILSLOT" : 
          ( IPX == pProto ) ? "IPX" : "UDP" );
        fprintf ( stdout, "\tEndpoint-> %s\n", 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] = '\0';    //
        // 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 %d\n", 
                  strlen (lpsMessage ), 
                  dwMessageID 
                  );    fprintf ( stdout, "MessageText->%s\n", 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] = '\0';
    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 %d\n", 
          strlen (lpsMessage ), 
          dwMessageID 
          );     fprintf ( stdout, "MessageText->%s\n", 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....Exiting\n"
      );
    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 %d\n", 
          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] = '\0';
        fprintf ( stdout, "A Udp Datagram of length %d bytes received from ", err );
        fprintf ( stdout, "\n\tIP Adress->%s ", inet_ntoa ( saUdpCli.sin_addr ) );
        fprintf ( stdout, "\n\tPort Number->%d\n", ntohs ( saUdpCli.sin_port ) );
        fprintf ( stdout, "MessageText->%s\n", 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 broadcasted\n", 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] = '\0';
        fprintf ( stdout, 
          "An Ipx Datagram of length %d bytes received from ", 
          err );
        fprintf ( stdout, 
          "\n\tIPX Adress->%s ", 
          IpxnetAddr ( achAddress, 
       saIpxCli.sa_netnum, 
       saIpxCli.sa_nodenum 
       ) 
          );
        fprintf ( stdout, "\n\tSocket Number->%d\n", saIpxCli.sa_socket );
        fprintf ( stdout, "MessageText->%s\n", 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 broadcasted\n", err);    //
        // Call the cleanup routine.
        //
        DoCleanup ( );    return;
    }//
    // Usage () lists the available command line options.
    //
    void __stdcall
    Usage (
        CHAR *pszProgramName
    )
    {
        fprintf ( stderr, "Usage:  %s\n", 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 client\n" );
        fprintf ( stderr, 
    "\n\tDefault Values-> Role:Server, Protocol:UDP, EndPoint:5005\n" );
        
    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 %d\n", 
          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, "DONE\n" );    return;
    }
      

  3.   

    上例对广播演示的非常明了,用SOCKET有IPX 和 UDP 两种,还实现的一种用邮槽的广播方法,看看吧