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 stay on the subnet you're a part of.

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


// page04.html,v 1.11 1999/09/22 03:13:43 jcej Exp

#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[BUFSIZ];

  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,
                  ACE_OS::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_name(),
              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.
Ok, one more warning:
If you happen to have multiple servers running on your network when you invoke this client, the response could come from any one of them.


[Tutorial Index] [Continue This Tutorial]