summaryrefslogtreecommitdiff
path: root/docs/tutorials/008/page04.html
blob: 4a634b56a4b6b50c52c9c9d919dc0052998a7bd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (WinNT; I) [Netscape]">
   <META NAME="Author" CONTENT="James CE Johnson">
   <TITLE>ACE Tutorial 008</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER>

<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER>


<P>
<HR WIDTH="100%">
<BR>&nbsp;
<BR>&nbsp;In <A HREF="broadcast_client.cpp">broadcast_client.cpp</A> we
find out how to send a single datagram to every host on our (sub)network.&nbsp;
I have to say <I>(sub)network</I> because broadcast datagrams typically
are not passed through routers.&nbsp; 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.

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

<P>
<HR WIDTH="100%">

<P><TT>#include "ace/SOCK_Dgram_Bcast.h"</TT>
<BR><TT>#include "ace/INET_Addr.h"</TT>

<P><TT>static const u_short PORT = ACE_DEFAULT_SERVER_PORT;</TT>

<P><TT>int main(int argc,char *argv[] )</TT>
<BR><TT>{</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE_INET_Addr&nbsp;
local((u_short)0);</TT>

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

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( dgram.open(local)
== -1 )</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "datagram open"),-1);</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char buf[512];</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sprintf(buf, "Hello World!");</TT>

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

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

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

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( dgram.recv(buf,sizeof(buf),remote)
== -1 )</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "recv"),-1);</TT>
<BR><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</TT>

<P><TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACE_DEBUG ((LM_DEBUG,
"(%P|%t) The server said:&nbsp; %s\n",buf));</TT>

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

<P>
<HR WIDTH="100%">

<P>&nbsp;About that subnet thing:
<BLOCKQUOTE>If you run this client on a host that has multiple network
interfaces, the broadcast will go to all of those (sub)networks.&nbsp;
What do you do, though, if you need to get past a router?&nbsp; My advice
is to write a server that will run on hosts on both sides of your router.&nbsp;
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.&nbsp;
The counterpart would then re-broadcast the original datagram on that sub-net.&nbsp;
Cheap, simple and effective.</BLOCKQUOTE>
One final word of warning:
<BLOCKQUOTE>When creating your broadcast datagrams you may see something
like this:&nbsp; <I>ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not
enable for this interface.: Unknown error</I>.&nbsp; There are some interfaces
(ppp, slip) that don't support broadcast datagrams.&nbsp; That's what you're
seeing here.</BLOCKQUOTE>

<HR WIDTH="100%">
<CENTER>[<A HREF="..">Tutorial Index</A>] [<A HREF="page05.html">Continue
This Tutorial</A>]</CENTER>

</BODY>
</HTML>