KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > net > MulticastSocket


1 /*
2  * @(#)MulticastSocket.java 1.72 05/11/17
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.net;
9
10 import java.io.IOException JavaDoc;
11 import java.io.InterruptedIOException JavaDoc;
12 import java.util.Enumeration JavaDoc;
13
14 /**
15  * The multicast datagram socket class is useful for sending
16  * and receiving IP multicast packets. A MulticastSocket is
17  * a (UDP) DatagramSocket, with additional capabilities for
18  * joining "groups" of other multicast hosts on the internet.
19  * <P>
20  * A multicast group is specified by a class D IP address
21  * and by a standard UDP port number. Class D IP addresses
22  * are in the range <CODE>224.0.0.0</CODE> to <CODE>239.255.255.255</CODE>,
23  * inclusive. The address 224.0.0.0 is reserved and should not be used.
24  * <P>
25  * One would join a multicast group by first creating a MulticastSocket
26  * with the desired port, then invoking the
27  * <CODE>joinGroup(InetAddress groupAddr)</CODE>
28  * method:
29  * <PRE>
30  * // join a Multicast group and send the group salutations
31  * ...
32  * String msg = "Hello";
33  * InetAddress group = InetAddress.getByName("228.5.6.7");
34  * MulticastSocket s = new MulticastSocket(6789);
35  * s.joinGroup(group);
36  * DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
37  * group, 6789);
38  * s.send(hi);
39  * // get their responses!
40  * byte[] buf = new byte[1000];
41  * DatagramPacket recv = new DatagramPacket(buf, buf.length);
42  * s.receive(recv);
43  * ...
44  * // OK, I'm done talking - leave the group...
45  * s.leaveGroup(group);
46  * </PRE>
47  *
48  * When one sends a message to a multicast group, <B>all</B> subscribing
49  * recipients to that host and port receive the message (within the
50  * time-to-live range of the packet, see below). The socket needn't
51  * be a member of the multicast group to send messages to it.
52  * <P>
53  * When a socket subscribes to a multicast group/port, it receives
54  * datagrams sent by other hosts to the group/port, as do all other
55  * members of the group and port. A socket relinquishes membership
56  * in a group by the leaveGroup(InetAddress addr) method. <B>
57  * Multiple MulticastSocket's</B> may subscribe to a multicast group
58  * and port concurrently, and they will all receive group datagrams.
59  * <P>
60  * Currently applets are not allowed to use multicast sockets.
61  *
62  * @author Pavani Diwanji
63  * @since JDK1.1
64  */

65 public
66 class MulticastSocket extends DatagramSocket JavaDoc {
67     /**
68      * Create a multicast socket.
69      *
70      * <p>If there is a security manager,
71      * its <code>checkListen</code> method is first called
72      * with 0 as its argument to ensure the operation is allowed.
73      * This could result in a SecurityException.
74      * <p>
75      * When the socket is created the
76      * {@link DatagramSocket#setReuseAddress(boolean)} method is
77      * called to enable the SO_REUSEADDR socket option.
78      *
79      * @exception IOException if an I/O exception occurs
80      * while creating the MulticastSocket
81      * @exception SecurityException if a security manager exists and its
82      * <code>checkListen</code> method doesn't allow the operation.
83      * @see SecurityManager#checkListen
84      * @see java.net.DatagramSocket#setReuseAddress(boolean)
85      */

86     public MulticastSocket() throws IOException JavaDoc {
87     this(new InetSocketAddress JavaDoc(0));
88     }
89
90     /**
91      * Create a multicast socket and bind it to a specific port.
92      *
93      * <p>If there is a security manager,
94      * its <code>checkListen</code> method is first called
95      * with the <code>port</code> argument
96      * as its argument to ensure the operation is allowed.
97      * This could result in a SecurityException.
98      * <p>
99      * When the socket is created the
100      * {@link DatagramSocket#setReuseAddress(boolean)} method is
101      * called to enable the SO_REUSEADDR socket option.
102      *
103      * @param port port to use
104      * @exception IOException if an I/O exception occurs
105      * while creating the MulticastSocket
106      * @exception SecurityException if a security manager exists and its
107      * <code>checkListen</code> method doesn't allow the operation.
108      * @see SecurityManager#checkListen
109      * @see java.net.DatagramSocket#setReuseAddress(boolean)
110      */

111     public MulticastSocket(int port) throws IOException JavaDoc {
112     this(new InetSocketAddress JavaDoc(port));
113     }
114
115     /**
116      * Create a MulticastSocket bound to the specified socket address.
117      * <p>
118      * Or, if the address is <code>null</code>, create an unbound socket.
119      * <p>
120      * <p>If there is a security manager,
121      * its <code>checkListen</code> method is first called
122      * with the SocketAddress port as its argument to ensure the operation is allowed.
123      * This could result in a SecurityException.
124      * <p>
125      * When the socket is created the
126      * {@link DatagramSocket#setReuseAddress(boolean)} method is
127      * called to enable the SO_REUSEADDR socket option.
128      *
129      * @param bindaddr Socket address to bind to, or <code>null</code> for
130      * an unbound socket.
131      * @exception IOException if an I/O exception occurs
132      * while creating the MulticastSocket
133      * @exception SecurityException if a security manager exists and its
134      * <code>checkListen</code> method doesn't allow the operation.
135      * @see SecurityManager#checkListen
136      * @see java.net.DatagramSocket#setReuseAddress(boolean)
137      *
138      * @since 1.4
139      */

140     public MulticastSocket(SocketAddress JavaDoc bindaddr) throws IOException JavaDoc {
141     super((SocketAddress JavaDoc) null);
142
143     // Enable SO_REUSEADDR before binding
144
setReuseAddress(true);
145
146     if (bindaddr != null) {
147         bind(bindaddr);
148     }
149     }
150
151     /**
152      * The lock on the socket's TTL. This is for set/getTTL and
153      * send(packet,ttl).
154      */

155     private Object JavaDoc ttlLock = new Object JavaDoc();
156
157     /**
158      * The lock on the socket's interface - used by setInterface
159      * and getInterface
160      */

161     private Object JavaDoc infLock = new Object JavaDoc();
162
163     /**
164      * The "last" interface set by setInterface on this MulticastSocket
165      */

166     private InetAddress JavaDoc infAddress = null;
167
168
169     /**
170      * Set the default time-to-live for multicast packets sent out
171      * on this <code>MulticastSocket</code> in order to control the
172      * scope of the multicasts.
173      *
174      * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be
175      * in the range <code> 0 <= ttl <= 0xFF </code>.
176      *
177      * @param ttl the time-to-live
178      * @exception IOException if an I/O exception occurs
179      * while setting the default time-to-live value
180      * @deprecated use the setTimeToLive method instead, which uses
181      * <b>int</b> instead of <b>byte</b> as the type for ttl.
182      * @see #getTTL()
183      */

184     @Deprecated JavaDoc
185     public void setTTL(byte ttl) throws IOException JavaDoc {
186     if (isClosed())
187         throw new SocketException JavaDoc("Socket is closed");
188     getImpl().setTTL(ttl);
189     }
190
191     /**
192      * Set the default time-to-live for multicast packets sent out
193      * on this <code>MulticastSocket</code> in order to control the
194      * scope of the multicasts.
195      *
196      * <P> The ttl <B>must</B> be in the range <code> 0 <= ttl <=
197      * 255</code> or an IllegalArgumentException will be thrown.
198      * @exception IOException if an I/O exception occurs
199      * while setting the default time-to-live value
200      * @param ttl the time-to-live
201      * @see #getTimeToLive()
202      */

203     public void setTimeToLive(int ttl) throws IOException JavaDoc {
204     if (ttl < 0 || ttl > 255) {
205         throw new IllegalArgumentException JavaDoc("ttl out of range");
206     }
207     if (isClosed())
208         throw new SocketException JavaDoc("Socket is closed");
209     getImpl().setTimeToLive(ttl);
210     }
211
212     /**
213      * Get the default time-to-live for multicast packets sent out on
214      * the socket.
215      *
216      * @exception IOException if an I/O exception occurs
217      * while getting the default time-to-live value
218      * @return the default time-to-live value
219      * @deprecated use the getTimeToLive method instead, which returns
220      * an <b>int</b> instead of a <b>byte</b>.
221      * @see #setTTL(byte)
222      */

223     @Deprecated JavaDoc
224     public byte getTTL() throws IOException JavaDoc {
225     if (isClosed())
226         throw new SocketException JavaDoc("Socket is closed");
227     return getImpl().getTTL();
228     }
229
230     /**
231      * Get the default time-to-live for multicast packets sent out on
232      * the socket.
233      * @exception IOException if an I/O exception occurs while
234      * getting the default time-to-live value
235      * @return the default time-to-live value
236      * @see #setTimeToLive(int)
237      */

238     public int getTimeToLive() throws IOException JavaDoc {
239     if (isClosed())
240         throw new SocketException JavaDoc("Socket is closed");
241     return getImpl().getTimeToLive();
242     }
243
244     /**
245      * Joins a multicast group. Its behavior may be affected by
246      * <code>setInterface</code> or <code>setNetworkInterface</code>.
247      *
248      * <p>If there is a security manager, this method first
249      * calls its <code>checkMulticast</code> method
250      * with the <code>mcastaddr</code> argument
251      * as its argument.
252      *
253      * @param mcastaddr is the multicast address to join
254      *
255      * @exception IOException if there is an error joining
256      * or when the address is not a multicast address.
257      * @exception SecurityException if a security manager exists and its
258      * <code>checkMulticast</code> method doesn't allow the join.
259      *
260      * @see SecurityManager#checkMulticast(InetAddress)
261      */

262     public void joinGroup(InetAddress JavaDoc mcastaddr) throws IOException JavaDoc {
263         if (isClosed()) {
264             throw new SocketException JavaDoc("Socket is closed");
265         }
266
267         SecurityManager JavaDoc security = System.getSecurityManager();
268         if (security != null) {
269             security.checkMulticast(mcastaddr);
270         }
271
272     if (!mcastaddr.isMulticastAddress()) {
273         throw new SocketException JavaDoc("Not a multicast address");
274     }
275
276     getImpl().join(mcastaddr);
277     }
278
279     /**
280      * Leave a multicast group. Its behavior may be affected by
281      * <code>setInterface</code> or <code>setNetworkInterface</code>.
282      *
283      * <p>If there is a security manager, this method first
284      * calls its <code>checkMulticast</code> method
285      * with the <code>mcastaddr</code> argument
286      * as its argument.
287      *
288      * @param mcastaddr is the multicast address to leave
289      * @exception IOException if there is an error leaving
290      * or when the address is not a multicast address.
291      * @exception SecurityException if a security manager exists and its
292      * <code>checkMulticast</code> method doesn't allow the operation.
293      *
294      * @see SecurityManager#checkMulticast(InetAddress)
295      */

296     public void leaveGroup(InetAddress JavaDoc mcastaddr) throws IOException JavaDoc {
297         if (isClosed()) {
298             throw new SocketException JavaDoc("Socket is closed");
299         }
300
301         SecurityManager JavaDoc security = System.getSecurityManager();
302         if (security != null) {
303             security.checkMulticast(mcastaddr);
304         }
305
306     if (!mcastaddr.isMulticastAddress()) {
307             throw new SocketException JavaDoc("Not a multicast address");
308         }
309
310     getImpl().leave(mcastaddr);
311     }
312
313     /**
314      * Joins the specified multicast group at the specified interface.
315      *
316      * <p>If there is a security manager, this method first
317      * calls its <code>checkMulticast</code> method
318      * with the <code>mcastaddr</code> argument
319      * as its argument.
320      *
321      * @param mcastaddr is the multicast address to join
322      * @param netIf specifies the local interface to receive multicast
323      * datagram packets, or <i>null</i> to defer to the interface set by
324      * {@link MulticastSocket#setInterface(InetAddress)} or
325      * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
326      *
327      * @exception IOException if there is an error joining
328      * or when the address is not a multicast address.
329      * @exception SecurityException if a security manager exists and its
330      * <code>checkMulticast</code> method doesn't allow the join.
331      * @throws IllegalArgumentException if mcastaddr is null or is a
332      * SocketAddress subclass not supported by this socket
333      *
334      * @see SecurityManager#checkMulticast(InetAddress)
335      * @since 1.4
336      */

337     public void joinGroup(SocketAddress JavaDoc mcastaddr, NetworkInterface JavaDoc netIf)
338     throws IOException JavaDoc {
339     if (isClosed())
340         throw new SocketException JavaDoc("Socket is closed");
341
342     if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress JavaDoc))
343         throw new IllegalArgumentException JavaDoc("Unsupported address type");
344
345     if (oldImpl)
346         throw new UnsupportedOperationException JavaDoc();
347
348     SecurityManager JavaDoc security = System.getSecurityManager();
349     if (security != null) {
350         security.checkMulticast(((InetSocketAddress JavaDoc)mcastaddr).getAddress());
351     }
352
353     if (!((InetSocketAddress JavaDoc)mcastaddr).getAddress().isMulticastAddress()) {
354             throw new SocketException JavaDoc("Not a multicast address");
355         }
356
357     getImpl().joinGroup(mcastaddr, netIf);
358     }
359
360     /**
361      * Leave a multicast group on a specified local interface.
362      *
363      * <p>If there is a security manager, this method first
364      * calls its <code>checkMulticast</code> method
365      * with the <code>mcastaddr</code> argument
366      * as its argument.
367      *
368      * @param mcastaddr is the multicast address to leave
369      * @param netIf specifies the local interface or <i>null</i> to defer
370      * to the interface set by
371      * {@link MulticastSocket#setInterface(InetAddress)} or
372      * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
373      * @exception IOException if there is an error leaving
374      * or when the address is not a multicast address.
375      * @exception SecurityException if a security manager exists and its
376      * <code>checkMulticast</code> method doesn't allow the operation.
377      * @throws IllegalArgumentException if mcastaddr is null or is a
378      * SocketAddress subclass not supported by this socket
379      *
380      * @see SecurityManager#checkMulticast(InetAddress)
381      * @since 1.4
382      */

383     public void leaveGroup(SocketAddress JavaDoc mcastaddr, NetworkInterface JavaDoc netIf)
384     throws IOException JavaDoc {
385     if (isClosed())
386         throw new SocketException JavaDoc("Socket is closed");
387
388     if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress JavaDoc))
389         throw new IllegalArgumentException JavaDoc("Unsupported address type");
390
391     if (oldImpl)
392         throw new UnsupportedOperationException JavaDoc();
393
394     SecurityManager JavaDoc security = System.getSecurityManager();
395     if (security != null) {
396         security.checkMulticast(((InetSocketAddress JavaDoc)mcastaddr).getAddress());
397     }
398
399     if (!((InetSocketAddress JavaDoc)mcastaddr).getAddress().isMulticastAddress()) {
400         throw new SocketException JavaDoc("Not a multicast address");
401     }
402
403     getImpl().leaveGroup(mcastaddr, netIf);
404      }
405
406     /**
407      * Set the multicast network interface used by methods
408      * whose behavior would be affected by the value of the
409      * network interface. Useful for multihomed hosts.
410      * @param inf the InetAddress
411      * @exception SocketException if there is an error in
412      * the underlying protocol, such as a TCP error.
413      * @see #getInterface()
414      */

415     public void setInterface(InetAddress JavaDoc inf) throws SocketException JavaDoc {
416     if (isClosed()) {
417         throw new SocketException JavaDoc("Socket is closed");
418     }
419     synchronized (infLock) {
420         getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
421         infAddress = inf;
422     }
423     }
424
425     /**
426      * Retrieve the address of the network interface used for
427      * multicast packets.
428      *
429      * @return An <code>InetAddress</code> representing
430      * the address of the network interface used for
431      * multicast packets.
432      *
433      * @exception SocketException if there is an error in
434      * the underlying protocol, such as a TCP error.
435      *
436      * @see #setInterface(java.net.InetAddress)
437      */

438     public InetAddress JavaDoc getInterface() throws SocketException JavaDoc {
439     if (isClosed()) {
440         throw new SocketException JavaDoc("Socket is closed");
441     }
442     synchronized (infLock) {
443         InetAddress JavaDoc ia =
444         (InetAddress JavaDoc)getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
445
446         /**
447          * No previous setInterface or interface can be
448          * set using setNetworkInterface
449          */

450         if (infAddress == null) {
451         return ia;
452         }
453
454         /**
455          * Same interface set with setInterface?
456          */

457         if (ia.equals(infAddress)) {
458         return ia;
459         }
460
461         /**
462          * Different InetAddress from what we set with setInterface
463          * so enumerate the current interface to see if the
464          * address set by setInterface is bound to this interface.
465          */

466         try {
467         NetworkInterface JavaDoc ni = NetworkInterface.getByInetAddress(ia);
468         Enumeration JavaDoc addrs = ni.getInetAddresses();
469         while (addrs.hasMoreElements()) {
470             InetAddress JavaDoc addr = (InetAddress JavaDoc)(addrs.nextElement());
471             if (addr.equals(infAddress)) {
472             return infAddress;
473             }
474         }
475
476         /**
477          * No match so reset infAddress to indicate that the
478          * interface has changed via means
479          */

480         infAddress = null;
481         return ia;
482         } catch (Exception JavaDoc e) {
483         return ia;
484         }
485     }
486     }
487
488     /**
489      * Specify the network interface for outgoing multicast datagrams
490      * sent on this socket.
491      *
492      * @param netIf the interface
493      * @exception SocketException if there is an error in
494      * the underlying protocol, such as a TCP error.
495      * @see #getNetworkInterface()
496      * @since 1.4
497      */

498     public void setNetworkInterface(NetworkInterface JavaDoc netIf)
499     throws SocketException JavaDoc {
500
501     synchronized (infLock) {
502         getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf);
503         infAddress = null;
504     }
505     }
506
507     /**
508      * Get the multicast network interface set.
509      *
510      * @exception SocketException if there is an error in
511      * the underlying protocol, such as a TCP error.
512      * @return the multicast <code>NetworkInterface</code> currently set
513      * @see #setNetworkInterface(NetworkInterface)
514      * @since 1.4
515      */

516     public NetworkInterface JavaDoc getNetworkInterface() throws SocketException JavaDoc {
517     NetworkInterface JavaDoc ni
518         = (NetworkInterface JavaDoc)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
519     if (ni.getIndex() == 0) {
520         InetAddress JavaDoc[] addrs = new InetAddress JavaDoc[1];
521         addrs[0] = InetAddress.anyLocalAddress();
522         return new NetworkInterface JavaDoc(addrs[0].getHostName(), 0, addrs);
523     } else {
524         return ni;
525     }
526     }
527
528     /**
529      * Disable/Enable local loopback of multicast datagrams
530      * The option is used by the platform's networking code as a hint
531      * for setting whether multicast data will be looped back to
532      * the local socket.
533      *
534      * <p>Because this option is a hint, applications that want to
535      * verify what loopback mode is set to should call
536      * {@link #getLoopbackMode()}
537      * @param disable <code>true</code> to disable the LoopbackMode
538      * @throws SocketException if an error occurs while setting the value
539      * @since 1.4
540      * @see #getLoopbackMode
541      */

542     public void setLoopbackMode(boolean disable) throws SocketException JavaDoc {
543     getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable));
544     }
545     
546     /**
547      * Get the setting for local loopback of multicast datagrams.
548      *
549      * @throws SocketException if an error occurs while getting the value
550      * @return true if the LoopbackMode has been disabled
551      * @since 1.4
552      * @see #setLoopbackMode
553      */

554     public boolean getLoopbackMode() throws SocketException JavaDoc {
555     return ((Boolean JavaDoc)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue();
556     }
557
558     /**
559      * Sends a datagram packet to the destination, with a TTL (time-
560      * to-live) other than the default for the socket. This method
561      * need only be used in instances where a particular TTL is desired;
562      * otherwise it is preferable to set a TTL once on the socket, and
563      * use that default TTL for all packets. This method does <B>not
564      * </B> alter the default TTL for the socket. Its behavior may be
565      * affected by <code>setInterface</code>.
566      *
567      * <p>If there is a security manager, this method first performs some
568      * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
569      * is true, this method calls the
570      * security manager's <code>checkMulticast</code> method
571      * with <code>p.getAddress()</code> and <code>ttl</code> as its arguments.
572      * If the evaluation of that expression is false,
573      * this method instead calls the security manager's
574      * <code>checkConnect</code> method with arguments
575      * <code>p.getAddress().getHostAddress()</code> and
576      * <code>p.getPort()</code>. Each call to a security manager method
577      * could result in a SecurityException if the operation is not allowed.
578      *
579      * @param p is the packet to be sent. The packet should contain
580      * the destination multicast ip address and the data to be sent.
581      * One does not need to be the member of the group to send
582      * packets to a destination multicast address.
583      * @param ttl optional time to live for multicast packet.
584      * default ttl is 1.
585      *
586      * @exception IOException is raised if an error occurs i.e
587      * error while setting ttl.
588      * @exception SecurityException if a security manager exists and its
589      * <code>checkMulticast</code> or <code>checkConnect</code>
590      * method doesn't allow the send.
591      *
592      * @deprecated Use the following code or its equivalent instead:
593      * ......
594      * int ttl = mcastSocket.getTimeToLive();
595      * mcastSocket.setTimeToLive(newttl);
596      * mcastSocket.send(p);
597      * mcastSocket.setTimeToLive(ttl);
598      * ......
599      *
600      * @see DatagramSocket#send
601      * @see DatagramSocket#receive
602      * @see SecurityManager#checkMulticast(java.net.InetAddress, byte)
603      * @see SecurityManager#checkConnect
604      */

605     @Deprecated JavaDoc
606     public void send(DatagramPacket JavaDoc p, byte ttl)
607         throws IOException JavaDoc {
608         if (isClosed())
609         throw new SocketException JavaDoc("Socket is closed");
610             synchronized(ttlLock) {
611                 synchronized(p) {
612             if (connectState == ST_NOT_CONNECTED) {
613                         // Security manager makes sure that the multicast address
614
// is allowed one and that the ttl used is less
615
// than the allowed maxttl.
616
SecurityManager JavaDoc security = System.getSecurityManager();
617                         if (security != null) {
618                             if (p.getAddress().isMulticastAddress()) {
619                                 security.checkMulticast(p.getAddress(), ttl);
620                             } else {
621                                 security.checkConnect(p.getAddress().getHostAddress(),
622                                                       p.getPort());
623                             }
624                         }
625             } else {
626             // we're connected
627
InetAddress JavaDoc packetAddress = null;
628             packetAddress = p.getAddress();
629             if (packetAddress == null) {
630                 p.setAddress(connectedAddress);
631                 p.setPort(connectedPort);
632             } else if ((!packetAddress.equals(connectedAddress)) ||
633                    p.getPort() != connectedPort) {
634                 throw new SecurityException JavaDoc("connected address and packet address" +
635                             " differ");
636             }
637             }
638                     byte dttl = getTTL();
639                     try {
640                         if (ttl != dttl) {
641                             // set the ttl
642
getImpl().setTTL(ttl);
643                         }
644                         // call the datagram method to send
645
getImpl().send(p);
646                     } finally {
647                         // set it back to default
648
if (ttl != dttl) {
649                             getImpl().setTTL(dttl);
650                         }
651                     }
652                 } // synch p
653
} //synch ttl
654
} //method
655
}
656
Popular Tags