jdk/src/share/classes/java/net/MulticastSocket.java
changeset 2 90ce3da70b43
child 5180 8161f879d704
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package java.net;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.io.InterruptedIOException;
       
    30 import java.util.Enumeration;
       
    31 
       
    32 /**
       
    33  * The multicast datagram socket class is useful for sending
       
    34  * and receiving IP multicast packets.  A MulticastSocket is
       
    35  * a (UDP) DatagramSocket, with additional capabilities for
       
    36  * joining "groups" of other multicast hosts on the internet.
       
    37  * <P>
       
    38  * A multicast group is specified by a class D IP address
       
    39  * and by a standard UDP port number. Class D IP addresses
       
    40  * are in the range <CODE>224.0.0.0</CODE> to <CODE>239.255.255.255</CODE>,
       
    41  * inclusive. The address 224.0.0.0 is reserved and should not be used.
       
    42  * <P>
       
    43  * One would join a multicast group by first creating a MulticastSocket
       
    44  * with the desired port, then invoking the
       
    45  * <CODE>joinGroup(InetAddress groupAddr)</CODE>
       
    46  * method:
       
    47  * <PRE>
       
    48  * // join a Multicast group and send the group salutations
       
    49  * ...
       
    50  * String msg = "Hello";
       
    51  * InetAddress group = InetAddress.getByName("228.5.6.7");
       
    52  * MulticastSocket s = new MulticastSocket(6789);
       
    53  * s.joinGroup(group);
       
    54  * DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
       
    55  *                             group, 6789);
       
    56  * s.send(hi);
       
    57  * // get their responses!
       
    58  * byte[] buf = new byte[1000];
       
    59  * DatagramPacket recv = new DatagramPacket(buf, buf.length);
       
    60  * s.receive(recv);
       
    61  * ...
       
    62  * // OK, I'm done talking - leave the group...
       
    63  * s.leaveGroup(group);
       
    64  * </PRE>
       
    65  *
       
    66  * When one sends a message to a multicast group, <B>all</B> subscribing
       
    67  * recipients to that host and port receive the message (within the
       
    68  * time-to-live range of the packet, see below).  The socket needn't
       
    69  * be a member of the multicast group to send messages to it.
       
    70  * <P>
       
    71  * When a socket subscribes to a multicast group/port, it receives
       
    72  * datagrams sent by other hosts to the group/port, as do all other
       
    73  * members of the group and port.  A socket relinquishes membership
       
    74  * in a group by the leaveGroup(InetAddress addr) method.  <B>
       
    75  * Multiple MulticastSocket's</B> may subscribe to a multicast group
       
    76  * and port concurrently, and they will all receive group datagrams.
       
    77  * <P>
       
    78  * Currently applets are not allowed to use multicast sockets.
       
    79  *
       
    80  * @author Pavani Diwanji
       
    81  * @since  JDK1.1
       
    82  */
       
    83 public
       
    84 class MulticastSocket extends DatagramSocket {
       
    85     /**
       
    86      * Create a multicast socket.
       
    87      *
       
    88      * <p>If there is a security manager,
       
    89      * its <code>checkListen</code> method is first called
       
    90      * with 0 as its argument to ensure the operation is allowed.
       
    91      * This could result in a SecurityException.
       
    92      * <p>
       
    93      * When the socket is created the
       
    94      * {@link DatagramSocket#setReuseAddress(boolean)} method is
       
    95      * called to enable the SO_REUSEADDR socket option.
       
    96      *
       
    97      * @exception IOException if an I/O exception occurs
       
    98      * while creating the MulticastSocket
       
    99      * @exception  SecurityException  if a security manager exists and its
       
   100      *             <code>checkListen</code> method doesn't allow the operation.
       
   101      * @see SecurityManager#checkListen
       
   102      * @see java.net.DatagramSocket#setReuseAddress(boolean)
       
   103      */
       
   104     public MulticastSocket() throws IOException {
       
   105         this(new InetSocketAddress(0));
       
   106     }
       
   107 
       
   108     /**
       
   109      * Create a multicast socket and bind it to a specific port.
       
   110      *
       
   111      * <p>If there is a security manager,
       
   112      * its <code>checkListen</code> method is first called
       
   113      * with the <code>port</code> argument
       
   114      * as its argument to ensure the operation is allowed.
       
   115      * This could result in a SecurityException.
       
   116      * <p>
       
   117      * When the socket is created the
       
   118      * {@link DatagramSocket#setReuseAddress(boolean)} method is
       
   119      * called to enable the SO_REUSEADDR socket option.
       
   120      *
       
   121      * @param port port to use
       
   122      * @exception IOException if an I/O exception occurs
       
   123      * while creating the MulticastSocket
       
   124      * @exception  SecurityException  if a security manager exists and its
       
   125      *             <code>checkListen</code> method doesn't allow the operation.
       
   126      * @see SecurityManager#checkListen
       
   127      * @see java.net.DatagramSocket#setReuseAddress(boolean)
       
   128      */
       
   129     public MulticastSocket(int port) throws IOException {
       
   130         this(new InetSocketAddress(port));
       
   131     }
       
   132 
       
   133     /**
       
   134      * Create a MulticastSocket bound to the specified socket address.
       
   135      * <p>
       
   136      * Or, if the address is <code>null</code>, create an unbound socket.
       
   137      * <p>
       
   138      * <p>If there is a security manager,
       
   139      * its <code>checkListen</code> method is first called
       
   140      * with the SocketAddress port as its argument to ensure the operation is allowed.
       
   141      * This could result in a SecurityException.
       
   142      * <p>
       
   143      * When the socket is created the
       
   144      * {@link DatagramSocket#setReuseAddress(boolean)} method is
       
   145      * called to enable the SO_REUSEADDR socket option.
       
   146      *
       
   147      * @param bindaddr Socket address to bind to, or <code>null</code> for
       
   148      *                 an unbound socket.
       
   149      * @exception IOException if an I/O exception occurs
       
   150      * while creating the MulticastSocket
       
   151      * @exception  SecurityException  if a security manager exists and its
       
   152      *             <code>checkListen</code> method doesn't allow the operation.
       
   153      * @see SecurityManager#checkListen
       
   154      * @see java.net.DatagramSocket#setReuseAddress(boolean)
       
   155      *
       
   156      * @since 1.4
       
   157      */
       
   158     public MulticastSocket(SocketAddress bindaddr) throws IOException {
       
   159         super((SocketAddress) null);
       
   160 
       
   161         // Enable SO_REUSEADDR before binding
       
   162         setReuseAddress(true);
       
   163 
       
   164         if (bindaddr != null) {
       
   165             bind(bindaddr);
       
   166         }
       
   167     }
       
   168 
       
   169     /**
       
   170      * The lock on the socket's TTL. This is for set/getTTL and
       
   171      * send(packet,ttl).
       
   172      */
       
   173     private Object ttlLock = new Object();
       
   174 
       
   175     /**
       
   176      * The lock on the socket's interface - used by setInterface
       
   177      * and getInterface
       
   178      */
       
   179     private Object infLock = new Object();
       
   180 
       
   181     /**
       
   182      * The "last" interface set by setInterface on this MulticastSocket
       
   183      */
       
   184     private InetAddress infAddress = null;
       
   185 
       
   186 
       
   187     /**
       
   188      * Set the default time-to-live for multicast packets sent out
       
   189      * on this <code>MulticastSocket</code> in order to control the
       
   190      * scope of the multicasts.
       
   191      *
       
   192      * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be
       
   193      * in the range <code> 0 <= ttl <= 0xFF </code>.
       
   194      *
       
   195      * @param ttl the time-to-live
       
   196      * @exception IOException if an I/O exception occurs
       
   197      * while setting the default time-to-live value
       
   198      * @deprecated use the setTimeToLive method instead, which uses
       
   199      * <b>int</b> instead of <b>byte</b> as the type for ttl.
       
   200      * @see #getTTL()
       
   201      */
       
   202     @Deprecated
       
   203     public void setTTL(byte ttl) throws IOException {
       
   204         if (isClosed())
       
   205             throw new SocketException("Socket is closed");
       
   206         getImpl().setTTL(ttl);
       
   207     }
       
   208 
       
   209     /**
       
   210      * Set the default time-to-live for multicast packets sent out
       
   211      * on this {@code MulticastSocket} in order to control the
       
   212      * scope of the multicasts.
       
   213      *
       
   214      * <P> The ttl <B>must</B> be in the range {@code  0 <= ttl <=
       
   215      * 255} or an {@code IllegalArgumentException} will be thrown.
       
   216      * Multicast packets sent with a TTL of {@code 0} are not transmitted
       
   217      * on the network but may be delivered locally.
       
   218      *
       
   219      * @param  ttl
       
   220      *         the time-to-live
       
   221      *
       
   222      * @throws  IOException
       
   223      *          if an I/O exception occurs while setting the
       
   224      *          default time-to-live value
       
   225      *
       
   226      * @see #getTimeToLive()
       
   227      */
       
   228     public void setTimeToLive(int ttl) throws IOException {
       
   229         if (ttl < 0 || ttl > 255) {
       
   230             throw new IllegalArgumentException("ttl out of range");
       
   231         }
       
   232         if (isClosed())
       
   233             throw new SocketException("Socket is closed");
       
   234         getImpl().setTimeToLive(ttl);
       
   235     }
       
   236 
       
   237     /**
       
   238      * Get the default time-to-live for multicast packets sent out on
       
   239      * the socket.
       
   240      *
       
   241      * @exception IOException if an I/O exception occurs
       
   242      * while getting the default time-to-live value
       
   243      * @return the default time-to-live value
       
   244      * @deprecated use the getTimeToLive method instead, which returns
       
   245      * an <b>int</b> instead of a <b>byte</b>.
       
   246      * @see #setTTL(byte)
       
   247      */
       
   248     @Deprecated
       
   249     public byte getTTL() throws IOException {
       
   250         if (isClosed())
       
   251             throw new SocketException("Socket is closed");
       
   252         return getImpl().getTTL();
       
   253     }
       
   254 
       
   255     /**
       
   256      * Get the default time-to-live for multicast packets sent out on
       
   257      * the socket.
       
   258      * @exception IOException if an I/O exception occurs while
       
   259      * getting the default time-to-live value
       
   260      * @return the default time-to-live value
       
   261      * @see #setTimeToLive(int)
       
   262      */
       
   263     public int getTimeToLive() throws IOException {
       
   264         if (isClosed())
       
   265             throw new SocketException("Socket is closed");
       
   266         return getImpl().getTimeToLive();
       
   267     }
       
   268 
       
   269     /**
       
   270      * Joins a multicast group. Its behavior may be affected by
       
   271      * <code>setInterface</code> or <code>setNetworkInterface</code>.
       
   272      *
       
   273      * <p>If there is a security manager, this method first
       
   274      * calls its <code>checkMulticast</code> method
       
   275      * with the <code>mcastaddr</code> argument
       
   276      * as its argument.
       
   277      *
       
   278      * @param mcastaddr is the multicast address to join
       
   279      *
       
   280      * @exception IOException if there is an error joining
       
   281      * or when the address is not a multicast address.
       
   282      * @exception  SecurityException  if a security manager exists and its
       
   283      * <code>checkMulticast</code> method doesn't allow the join.
       
   284      *
       
   285      * @see SecurityManager#checkMulticast(InetAddress)
       
   286      */
       
   287     public void joinGroup(InetAddress mcastaddr) throws IOException {
       
   288         if (isClosed()) {
       
   289             throw new SocketException("Socket is closed");
       
   290         }
       
   291 
       
   292         SecurityManager security = System.getSecurityManager();
       
   293         if (security != null) {
       
   294             security.checkMulticast(mcastaddr);
       
   295         }
       
   296 
       
   297         if (!mcastaddr.isMulticastAddress()) {
       
   298             throw new SocketException("Not a multicast address");
       
   299         }
       
   300 
       
   301         getImpl().join(mcastaddr);
       
   302     }
       
   303 
       
   304     /**
       
   305      * Leave a multicast group. Its behavior may be affected by
       
   306      * <code>setInterface</code> or <code>setNetworkInterface</code>.
       
   307      *
       
   308      * <p>If there is a security manager, this method first
       
   309      * calls its <code>checkMulticast</code> method
       
   310      * with the <code>mcastaddr</code> argument
       
   311      * as its argument.
       
   312      *
       
   313      * @param mcastaddr is the multicast address to leave
       
   314      * @exception IOException if there is an error leaving
       
   315      * or when the address is not a multicast address.
       
   316      * @exception  SecurityException  if a security manager exists and its
       
   317      * <code>checkMulticast</code> method doesn't allow the operation.
       
   318      *
       
   319      * @see SecurityManager#checkMulticast(InetAddress)
       
   320      */
       
   321     public void leaveGroup(InetAddress mcastaddr) throws IOException {
       
   322         if (isClosed()) {
       
   323             throw new SocketException("Socket is closed");
       
   324         }
       
   325 
       
   326         SecurityManager security = System.getSecurityManager();
       
   327         if (security != null) {
       
   328             security.checkMulticast(mcastaddr);
       
   329         }
       
   330 
       
   331         if (!mcastaddr.isMulticastAddress()) {
       
   332             throw new SocketException("Not a multicast address");
       
   333         }
       
   334 
       
   335         getImpl().leave(mcastaddr);
       
   336     }
       
   337 
       
   338     /**
       
   339      * Joins the specified multicast group at the specified interface.
       
   340      *
       
   341      * <p>If there is a security manager, this method first
       
   342      * calls its <code>checkMulticast</code> method
       
   343      * with the <code>mcastaddr</code> argument
       
   344      * as its argument.
       
   345      *
       
   346      * @param mcastaddr is the multicast address to join
       
   347      * @param netIf specifies the local interface to receive multicast
       
   348      *        datagram packets, or <i>null</i> to defer to the interface set by
       
   349      *       {@link MulticastSocket#setInterface(InetAddress)} or
       
   350      *       {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
       
   351      *
       
   352      * @exception IOException if there is an error joining
       
   353      * or when the address is not a multicast address.
       
   354      * @exception  SecurityException  if a security manager exists and its
       
   355      * <code>checkMulticast</code> method doesn't allow the join.
       
   356      * @throws  IllegalArgumentException if mcastaddr is null or is a
       
   357      *          SocketAddress subclass not supported by this socket
       
   358      *
       
   359      * @see SecurityManager#checkMulticast(InetAddress)
       
   360      * @since 1.4
       
   361      */
       
   362     public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
       
   363         throws IOException {
       
   364         if (isClosed())
       
   365             throw new SocketException("Socket is closed");
       
   366 
       
   367         if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
       
   368             throw new IllegalArgumentException("Unsupported address type");
       
   369 
       
   370         if (oldImpl)
       
   371             throw new UnsupportedOperationException();
       
   372 
       
   373         SecurityManager security = System.getSecurityManager();
       
   374         if (security != null) {
       
   375             security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
       
   376         }
       
   377 
       
   378         if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
       
   379             throw new SocketException("Not a multicast address");
       
   380         }
       
   381 
       
   382         getImpl().joinGroup(mcastaddr, netIf);
       
   383     }
       
   384 
       
   385     /**
       
   386      * Leave a multicast group on a specified local interface.
       
   387      *
       
   388      * <p>If there is a security manager, this method first
       
   389      * calls its <code>checkMulticast</code> method
       
   390      * with the <code>mcastaddr</code> argument
       
   391      * as its argument.
       
   392      *
       
   393      * @param mcastaddr is the multicast address to leave
       
   394      * @param netIf specifies the local interface or <i>null</i> to defer
       
   395      *             to the interface set by
       
   396      *             {@link MulticastSocket#setInterface(InetAddress)} or
       
   397      *             {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
       
   398      * @exception IOException if there is an error leaving
       
   399      * or when the address is not a multicast address.
       
   400      * @exception  SecurityException  if a security manager exists and its
       
   401      * <code>checkMulticast</code> method doesn't allow the operation.
       
   402      * @throws  IllegalArgumentException if mcastaddr is null or is a
       
   403      *          SocketAddress subclass not supported by this socket
       
   404      *
       
   405      * @see SecurityManager#checkMulticast(InetAddress)
       
   406      * @since 1.4
       
   407      */
       
   408     public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
       
   409         throws IOException {
       
   410         if (isClosed())
       
   411             throw new SocketException("Socket is closed");
       
   412 
       
   413         if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
       
   414             throw new IllegalArgumentException("Unsupported address type");
       
   415 
       
   416         if (oldImpl)
       
   417             throw new UnsupportedOperationException();
       
   418 
       
   419         SecurityManager security = System.getSecurityManager();
       
   420         if (security != null) {
       
   421             security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress());
       
   422         }
       
   423 
       
   424         if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) {
       
   425             throw new SocketException("Not a multicast address");
       
   426         }
       
   427 
       
   428         getImpl().leaveGroup(mcastaddr, netIf);
       
   429      }
       
   430 
       
   431     /**
       
   432      * Set the multicast network interface used by methods
       
   433      * whose behavior would be affected by the value of the
       
   434      * network interface. Useful for multihomed hosts.
       
   435      * @param inf the InetAddress
       
   436      * @exception SocketException if there is an error in
       
   437      * the underlying protocol, such as a TCP error.
       
   438      * @see #getInterface()
       
   439      */
       
   440     public void setInterface(InetAddress inf) throws SocketException {
       
   441         if (isClosed()) {
       
   442             throw new SocketException("Socket is closed");
       
   443         }
       
   444         synchronized (infLock) {
       
   445             getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf);
       
   446             infAddress = inf;
       
   447         }
       
   448     }
       
   449 
       
   450     /**
       
   451      * Retrieve the address of the network interface used for
       
   452      * multicast packets.
       
   453      *
       
   454      * @return An <code>InetAddress</code> representing
       
   455      *  the address of the network interface used for
       
   456      *  multicast packets.
       
   457      *
       
   458      * @exception SocketException if there is an error in
       
   459      * the underlying protocol, such as a TCP error.
       
   460      *
       
   461      * @see #setInterface(java.net.InetAddress)
       
   462      */
       
   463     public InetAddress getInterface() throws SocketException {
       
   464         if (isClosed()) {
       
   465             throw new SocketException("Socket is closed");
       
   466         }
       
   467         synchronized (infLock) {
       
   468             InetAddress ia =
       
   469                 (InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
       
   470 
       
   471             /**
       
   472              * No previous setInterface or interface can be
       
   473              * set using setNetworkInterface
       
   474              */
       
   475             if (infAddress == null) {
       
   476                 return ia;
       
   477             }
       
   478 
       
   479             /**
       
   480              * Same interface set with setInterface?
       
   481              */
       
   482             if (ia.equals(infAddress)) {
       
   483                 return ia;
       
   484             }
       
   485 
       
   486             /**
       
   487              * Different InetAddress from what we set with setInterface
       
   488              * so enumerate the current interface to see if the
       
   489              * address set by setInterface is bound to this interface.
       
   490              */
       
   491             try {
       
   492                 NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
       
   493                 Enumeration addrs = ni.getInetAddresses();
       
   494                 while (addrs.hasMoreElements()) {
       
   495                     InetAddress addr = (InetAddress)(addrs.nextElement());
       
   496                     if (addr.equals(infAddress)) {
       
   497                         return infAddress;
       
   498                     }
       
   499                 }
       
   500 
       
   501                 /**
       
   502                  * No match so reset infAddress to indicate that the
       
   503                  * interface has changed via means
       
   504                  */
       
   505                 infAddress = null;
       
   506                 return ia;
       
   507             } catch (Exception e) {
       
   508                 return ia;
       
   509             }
       
   510         }
       
   511     }
       
   512 
       
   513     /**
       
   514      * Specify the network interface for outgoing multicast datagrams
       
   515      * sent on this socket.
       
   516      *
       
   517      * @param netIf the interface
       
   518      * @exception SocketException if there is an error in
       
   519      * the underlying protocol, such as a TCP error.
       
   520      * @see #getNetworkInterface()
       
   521      * @since 1.4
       
   522      */
       
   523     public void setNetworkInterface(NetworkInterface netIf)
       
   524         throws SocketException {
       
   525 
       
   526         synchronized (infLock) {
       
   527             getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf);
       
   528             infAddress = null;
       
   529         }
       
   530     }
       
   531 
       
   532     /**
       
   533      * Get the multicast network interface set.
       
   534      *
       
   535      * @exception SocketException if there is an error in
       
   536      * the underlying protocol, such as a TCP error.
       
   537      * @return the multicast <code>NetworkInterface</code> currently set
       
   538      * @see #setNetworkInterface(NetworkInterface)
       
   539      * @since 1.4
       
   540      */
       
   541     public NetworkInterface getNetworkInterface() throws SocketException {
       
   542         NetworkInterface ni
       
   543             = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
       
   544         if (ni.getIndex() == 0) {
       
   545             InetAddress[] addrs = new InetAddress[1];
       
   546             addrs[0] = InetAddress.anyLocalAddress();
       
   547             return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
       
   548         } else {
       
   549             return ni;
       
   550         }
       
   551     }
       
   552 
       
   553     /**
       
   554      * Disable/Enable local loopback of multicast datagrams
       
   555      * The option is used by the platform's networking code as a hint
       
   556      * for setting whether multicast data will be looped back to
       
   557      * the local socket.
       
   558      *
       
   559      * <p>Because this option is a hint, applications that want to
       
   560      * verify what loopback mode is set to should call
       
   561      * {@link #getLoopbackMode()}
       
   562      * @param disable <code>true</code> to disable the LoopbackMode
       
   563      * @throws SocketException if an error occurs while setting the value
       
   564      * @since 1.4
       
   565      * @see #getLoopbackMode
       
   566      */
       
   567     public void setLoopbackMode(boolean disable) throws SocketException {
       
   568         getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable));
       
   569     }
       
   570 
       
   571     /**
       
   572      * Get the setting for local loopback of multicast datagrams.
       
   573      *
       
   574      * @throws SocketException  if an error occurs while getting the value
       
   575      * @return true if the LoopbackMode has been disabled
       
   576      * @since 1.4
       
   577      * @see #setLoopbackMode
       
   578      */
       
   579     public boolean getLoopbackMode() throws SocketException {
       
   580         return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue();
       
   581     }
       
   582 
       
   583     /**
       
   584      * Sends a datagram packet to the destination, with a TTL (time-
       
   585      * to-live) other than the default for the socket.  This method
       
   586      * need only be used in instances where a particular TTL is desired;
       
   587      * otherwise it is preferable to set a TTL once on the socket, and
       
   588      * use that default TTL for all packets.  This method does <B>not
       
   589      * </B> alter the default TTL for the socket. Its behavior may be
       
   590      * affected by <code>setInterface</code>.
       
   591      *
       
   592      * <p>If there is a security manager, this method first performs some
       
   593      * security checks. First, if <code>p.getAddress().isMulticastAddress()</code>
       
   594      * is true, this method calls the
       
   595      * security manager's <code>checkMulticast</code> method
       
   596      * with <code>p.getAddress()</code> and <code>ttl</code> as its arguments.
       
   597      * If the evaluation of that expression is false,
       
   598      * this method instead calls the security manager's
       
   599      * <code>checkConnect</code> method with arguments
       
   600      * <code>p.getAddress().getHostAddress()</code> and
       
   601      * <code>p.getPort()</code>. Each call to a security manager method
       
   602      * could result in a SecurityException if the operation is not allowed.
       
   603      *
       
   604      * @param p is the packet to be sent. The packet should contain
       
   605      * the destination multicast ip address and the data to be sent.
       
   606      * One does not need to be the member of the group to send
       
   607      * packets to a destination multicast address.
       
   608      * @param ttl optional time to live for multicast packet.
       
   609      * default ttl is 1.
       
   610      *
       
   611      * @exception IOException is raised if an error occurs i.e
       
   612      * error while setting ttl.
       
   613      * @exception  SecurityException  if a security manager exists and its
       
   614      *             <code>checkMulticast</code> or <code>checkConnect</code>
       
   615      *             method doesn't allow the send.
       
   616      *
       
   617      * @deprecated Use the following code or its equivalent instead:
       
   618      *  ......
       
   619      *  int ttl = mcastSocket.getTimeToLive();
       
   620      *  mcastSocket.setTimeToLive(newttl);
       
   621      *  mcastSocket.send(p);
       
   622      *  mcastSocket.setTimeToLive(ttl);
       
   623      *  ......
       
   624      *
       
   625      * @see DatagramSocket#send
       
   626      * @see DatagramSocket#receive
       
   627      * @see SecurityManager#checkMulticast(java.net.InetAddress, byte)
       
   628      * @see SecurityManager#checkConnect
       
   629      */
       
   630     @Deprecated
       
   631     public void send(DatagramPacket p, byte ttl)
       
   632         throws IOException {
       
   633             if (isClosed())
       
   634                 throw new SocketException("Socket is closed");
       
   635             synchronized(ttlLock) {
       
   636                 synchronized(p) {
       
   637                     if (connectState == ST_NOT_CONNECTED) {
       
   638                         // Security manager makes sure that the multicast address
       
   639                         // is allowed one and that the ttl used is less
       
   640                         // than the allowed maxttl.
       
   641                         SecurityManager security = System.getSecurityManager();
       
   642                         if (security != null) {
       
   643                             if (p.getAddress().isMulticastAddress()) {
       
   644                                 security.checkMulticast(p.getAddress(), ttl);
       
   645                             } else {
       
   646                                 security.checkConnect(p.getAddress().getHostAddress(),
       
   647                                                       p.getPort());
       
   648                             }
       
   649                         }
       
   650                     } else {
       
   651                         // we're connected
       
   652                         InetAddress packetAddress = null;
       
   653                         packetAddress = p.getAddress();
       
   654                         if (packetAddress == null) {
       
   655                             p.setAddress(connectedAddress);
       
   656                             p.setPort(connectedPort);
       
   657                         } else if ((!packetAddress.equals(connectedAddress)) ||
       
   658                                    p.getPort() != connectedPort) {
       
   659                             throw new SecurityException("connected address and packet address" +
       
   660                                                         " differ");
       
   661                         }
       
   662                     }
       
   663                     byte dttl = getTTL();
       
   664                     try {
       
   665                         if (ttl != dttl) {
       
   666                             // set the ttl
       
   667                             getImpl().setTTL(ttl);
       
   668                         }
       
   669                         // call the datagram method to send
       
   670                         getImpl().send(p);
       
   671                     } finally {
       
   672                         // set it back to default
       
   673                         if (ttl != dttl) {
       
   674                             getImpl().setTTL(dttl);
       
   675                         }
       
   676                     }
       
   677                 } // synch p
       
   678             }  //synch ttl
       
   679     } //method
       
   680 }