Most multicast servers are indiscriminate about who they will talk
to. Therefore, it’s easy to join a group—and watch the
data that’s being sent to it. Example 14.1 is a
MulticastSniffer
class that reads the name of a
multicast group from the command-line, constructs an
InetAddress
from that hostname, and then creates a
MulticastSocket
, which attempts to join the
multicast group at that hostname. If the attempt succeeds, it
receives datagrams from the socket and prints their contents on
System.out
. This program is useful primarily to
verify that you are receiving multicast data at a particular host.
Most multicast data is binary and won’t be intelligible when
printed as ASCII.
Example 14-1. Multicast Sniffer
import java.net.*; import java.io.*; public class MulticastSniffer { public static void main(String[] args) { InetAddress group = null; int port = 0; // read the address from the command line try { group = InetAddress.getByName(args[0]); port = Integer.parseInt(args[1]); } // end try catch (Exception e) { // ArrayIndexOutOfBoundsException, NumberFormatException, // or UnknownHostException System.err.println( "Usage: java MulticastSniffer multicast_address port"); System.exit(1); } MulticastSocket ms = null; try { ms = new MulticastSocket(port); ms.joinGroup(group); byte[] buffer = new byte[8192]; while (true) { DatagramPacket dp = new DatagramPacket(buffer, buffer.length); ms.receive(dp); String s = new String(dp.getData( )); System.out.println(s); } } catch (IOException e) { System.err.println(e); } finally { if (ms != null) { try { ms.leaveGroup(group); ms.close( ); } catch (IOException e) {} } } } }
The program begins by reading the name and port of the multicast
group from the first command-line argument. Next, we create a new
MulticastSocket
ms
on the
specified port. This socket joins the multicast group at the
specified InetAddress
. Then it enters a loop in
which it waits for packets to arrive. As each packet arrives, the
program reads its data, converts the data to an ISO Latin-1
String
, and prints it on
System.out
. Finally, when the user interrupts the
program or an exception is thrown, the socket leaves the group and
closes itself.
MBONE session announcements are broadcast to the multicast group http://sap.mcast.net on port 9,875. You can use this program to listen to those announcements. Generally, if you’re connected to the MBONE (not all sites are), then you should see a site announcement pop through within the first minute or two. In fact, you’ll probably see a lot more. I collected about a megabyte and a half of announcements within the first couple of minutes I had this program running. I show only the first two here:
% java MulticastSniffer sap.mcast.net 9875
úv=0
o=ellery 3132060082 3138107776 IN IP4 131.182.10.250
s=NASA TV - Broadcast from NASA HQ
i=NASA TV Multicasting from NASA HQ
u=http://www.nasa.gov/ntv
[email protected] (Ellery D. Coleman)
p=+202 651 8512
t=3138107776 3153918976
r=15811200 15811200 0
a=recvonly
a=tool:FVC.COM I-Caster V3.1/3101, Windows95/NT
a=cat:Corporate/Events
m=audio 23748 RTP/AVP 0
c=IN IP4 224.2.203.38/127
m=video 60068 RTP/AVP 31
c=IN IP4 224.2.203.37/127
b=AS:380
a=framerate:9
a=quality:8
a=grayed:0
4 224.2.255.115/15
.77/25
4 RTP wbbesteffort
c=IN IP4 224.2.224.41/25
¡_v=0
o=dax 3137417804 3141052115 IN IP4 horla.enst.fr
s=VREng UDP (Virtual Reality Engine)
i=Virtual Reality Engine: Distributed Interactive 3D Multicast
navigator in Virtual Worlds. For more information and downloading, see
URL: http://www.infres.enst.fr/net/vreng/.
u=http://www.infres.enst.fr/net/vreng/
e=Philippe Dax (ENST) <[email protected]>
p=Philippe Dax (ENST) +33 (0) 145817648
t=0 0
a=tool:sdr v2.9
a=type:test
m=dis 62239 RTP 99
c=IN IP4 224.2.199.133/127
/3
m=mdesk 64538 RTP/AVP mdesk
c=IN IP4 224.2.160.68/3
e please stop your receiving programs and the stream should stop from
coming to you.
u=http://tv.funet.fi/ohjelmat/index.html
e=Harri Salminen <[email protected]>
p=Harri Salminen +358 400 358 502
t=3085239600 3299658800
a=tool:CDT mAnnouncer 1.1.2
a=type:broadcast
m=audio 4004 RTP/AVP 0
c=IN IP4 239.239.239.239/40
a=ptime:40
m=video 6006 RTP/AVP 31
c=IN IP4 239.239.239.239/40
m=whiteboard 4206 udp wb
c=IN IP4 224.239.239.245/48
MBONE session announcements are not pure ASCII text. In particular,
they contain a lot of embedded nulls as well as various characters
with their high bit set. Consequently, I’ve had to take a few
liberties with the output to print it in this book. To really handle
MBONE session announcements, you’d have to parse the relevant
ASCII text out of the binary format and display that. Peter Parnes
has written a Java program called mSD that does exactly that. If
you’re interested, you can find it at http://www.cdt.luth.se/~peppar/progs/mSD/.
However, since this is a book about network programming and not
parsing binary file formats, we’ll leave our example here and
move on to sending multicast data. Example 14.2 is a
MulticastSender
class that sends data read from
the command-line to a multicast group. It is fairly simple overall.
Example 14-2. MulticastSender
import java.net.*; import java.io.*; public class MulticastSender { public static void main(String[] args) { InetAddress ia = null; int port = 0; byte ttl = (byte) 1; // read the address from the command line try { ia = InetAddress.getByName(args[0]); port = Integer.parseInt(args[1]); if (args.length > 2) ttl = (byte) Integer.parseInt(args[2]); } catch (Exception e) { System.err.println(e); System.err.println( "Usage: java MulticastSender multicast_address port ttl"); System.exit(1); } byte[] data = "Here's some multicast data ".getBytes( ); DatagramPacket dp = new DatagramPacket(data, data.length, ia, port); try { MulticastSocket ms = new MulticastSocket( ); ms.joinGroup(ia); for (int i = 1; i < 10; i++) { ms.send(dp, ttl); } ms.leaveGroup(ia); ms.close( ); } catch (SocketException se) { System.err.println(se); } catch (IOException ie) { System.err.println(ie); } } }
Example 14.2 reads the address of a multicast group,
a port number, and an optional TTL from the command line. It then
stuffs the string "Here's some
multicast data
"
into the byte array data
using
the getBytes( )
method of
java.lang.String
, and places this array in the
DatagramPacket
dp
. Next, it
constructs the MulticastSocket
ms
, which joins the group ia
.
Once it has joined the group, ms
sends the
datagram packet dp
to the group
ia
10 times. The TTL value is set to one to make
sure that this data doesn’t go beyond the local subnet. Having
sent the data, ms
leaves the group and closes
itself.
Run MulticastSniffer
on one machine in your local
subnet. Listen to the group all-systems.mcast.net on port 4,000 like
this:
% java MulticastSniffer all-systems.mcast.net 4000
Then send data to that group by running
MulticastSender
on another machine in your local
subnet. You can also run it in a different window on the same
machine, though that’s not as exciting. However, you must start
running the MulticastSniffer
before you start
running the MulticastSender
. Send to the group
all-systems.mcast.net on port
4,000 like this:
% java MulticastSender all-systems.mcast.net 4000
Back on the first machine you should see this output:
Here's some multicast data Here's some multicast data Here's some multicast data Here's some multicast data Here's some multicast data Here's some multicast data Here's some multicast data Here's some multicast data Here's some multicast data
For this to work beyond the local subnet, the two subnets will each have to have multicast routers.
3.139.79.59