ACE Tutorial 008
Sending and receiving datagrams



 
 In broadcast_client.cpp we find out how to send a single datagram to every host on our (sub)network.  I have to say (sub)network because broadcast datagrams typically are not passed through routers.  So, if your network admin has divided up your network into subnets, your broadcasts will likey only stay on the subnet you're a part of.

I've only commented the parts that are different from the directed_client.


#include "ace/SOCK_Dgram_Bcast.h"
#include "ace/INET_Addr.h"

static const u_short PORT = ACE_DEFAULT_SERVER_PORT;

int main(int argc,char *argv[] )
{
        ACE_INET_Addr  local((u_short)0);

        /*
           Instead of creating the ACE_SOCK_Dgram we created last time,
           we'll create an ACE_SOCK_Dgram_Bcast.  "Bcast" means, of course,
           "Broadcast".  This ACE object is clever enough to go out to the
           OS and find all of the network interfaces.  When you send()
           on a Dgram_Bcast, it will send the datagram out on all of those
           interfaces.  This is quiet handy if you do it on a multi-homed
           host that plays router...
         */
        ACE_SOCK_Dgram_Bcast dgram;

        if( dgram.open(local) == -1 )
        {
                ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "datagram open"),-1);
        }

        char buf[512];

        sprintf(buf, "Hello World!");

        /*
           The only other difference between us and the directed client
           is that we don't specify a host to receive the datagram.
           Instead, we use the magic value "INADDR_BROADCAST".  All hosts
           are obliged to respond to datagrams directed to this address
           the same as they would to datagrams sent to their hostname.

           Remember, the Dgram_Bcast will send a datagram to all interfaces
           on the host.  That's true even if the address is for a specific
           host (and the host address makes sense for the interface).
           The real power is in using an INADDR_BROADCAST addressed datagram
           against all interfaces.
         */
        ACE_INET_Addr  remote(PORT,INADDR_BROADCAST);

        ACE_DEBUG ((LM_DEBUG, "(%P|%t) Sending (%s) to the server.\n",buf));
 
        if( dgram.send(buf,strlen(buf)+1,remote) == -1 )
        {
                ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send"),-1);
        }

        if( dgram.recv(buf,sizeof(buf),remote) == -1 )
        {
                ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "recv"),-1);
        }

        ACE_DEBUG ((LM_DEBUG, "(%P|%t) The server said:  %s\n",buf));

        /*
           Using the remote object instance, find out where the server lives.
           We could then save this address and use directed datagrams to chat
           with the server for a while.
         */
        ACE_DEBUG ((LM_DEBUG, "(%P|%t) The server can be found at:  (%s:%d)\n",
                remote.get_host_addr(), PORT ));
 
        return(0);
}


 About that subnet thing:

If you run this client on a host that has multiple network interfaces, the broadcast will go to all of those (sub)networks.  What do you do, though, if you need to get past a router?  My advice is to write a server that will run on hosts on both sides of your router.  When a server on one side of the router receives a broadcast, it would send a directed datagram to it's counterpart on the other side of the router.  The counterpart would then re-broadcast the original datagram on that sub-net.  Cheap, simple and effective.
One final word of warning:
When creating your broadcast datagrams you may see something like this:  ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface.: Unknown error.  There are some interfaces (ppp, slip) that don't support broadcast datagrams.  That's what you're seeing here.

[Tutorial Index] [Continue This Tutorial]