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