< prev index next >

src/java.base/share/classes/java/net/DatagramSocket.java

Print this page
M DatagramSocket.java


   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.io.UncheckedIOException;
  30 import java.nio.channels.DatagramChannel;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedExceptionAction;
  33 import java.util.Objects;
  34 import java.util.Set;
  35 import java.util.Collections;
  36 
  37 /**
  38  * This class represents a socket for sending and receiving datagram packets.
  39  *
  40  * <p>A datagram socket is the sending or receiving point for a packet
  41  * delivery service. Each packet sent or received on a datagram socket
  42  * is individually addressed and routed. Multiple packets sent from
  43  * one machine to another may be routed differently, and may arrive in
  44  * any order.
  45  *
  46  * <p> Where possible, a newly constructed {@code DatagramSocket} has the
  47  * {@link StandardSocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as


 107  * can be useful when using a plain {@code DatagramSocket} to send datagrams to a
 108  * multicast group.
 109  *
 110  * @author  Pavani Diwanji
 111  * @see     java.net.DatagramPacket
 112  * @see     java.nio.channels.DatagramChannel
 113  * @since 1.0
 114  */
 115 public class DatagramSocket implements java.io.Closeable {
 116     /**
 117      * Various states of this socket.
 118      */
 119     private boolean bound = false;
 120     private boolean closed = false;
 121     private volatile boolean created;
 122     private final Object closeLock = new Object();
 123 
 124     /*
 125      * The implementation of this DatagramSocket.
 126      */

 127     private final DatagramSocketImpl impl;
 128 
 129     /**
 130      * Are we using an older DatagramSocketImpl?
 131      */
 132     final boolean oldImpl;
 133 
 134     /**
 135      * Set when a socket is ST_CONNECTED until we are certain
 136      * that any packets which might have been received prior
 137      * to calling connect() but not read by the application
 138      * have been read. During this time we check the source
 139      * address of all packets received to be sure they are from
 140      * the connected destination. Other packets are read but
 141      * silently dropped.
 142      */
 143     private boolean explicitFilter = false;
 144     private int bytesLeftToFilter;
 145     /*
 146      * Connection state:


 235      *
 236      * @throws     SocketException  if the socket could not be opened,
 237      *               or the socket could not bind to the specified local port.
 238      * @throws     SecurityException  if a security manager exists and its
 239      *             {@code checkListen} method doesn't allow the operation.
 240      *
 241      * @see SecurityManager#checkListen
 242      */
 243     public DatagramSocket() throws SocketException {
 244         this(new InetSocketAddress(0));
 245     }
 246 
 247     /**
 248      * Creates an unbound datagram socket with the specified
 249      * DatagramSocketImpl.
 250      *
 251      * @param impl an instance of a <B>DatagramSocketImpl</B>
 252      *        the subclass wishes to use on the DatagramSocket.
 253      * @since   1.4
 254      */
 255     protected DatagramSocket(DatagramSocketImpl impl) {
 256         if (impl == null)
 257             throw new NullPointerException();
 258         this.impl = impl;
 259         this.oldImpl = checkOldImpl(impl);
 260     }
 261 
 262     /**
 263      * Creates a datagram socket, bound to the specified local
 264      * socket address.
 265      * <p>
 266      * If, if the address is {@code null}, creates an unbound socket.
 267      *
 268      * <p>If there is a security manager,
 269      * its {@code checkListen} method is first called
 270      * with the port from the socket address
 271      * as its argument to ensure the operation is allowed.
 272      * This could result in a SecurityException.
 273      *
 274      * @param bindaddr local socket address to bind, or {@code null}
 275      *                 for an unbound socket.
 276      *
 277      * @throws     SocketException  if the socket could not be opened,
 278      *               or the socket could not bind to the specified local port.
 279      * @throws     SecurityException  if a security manager exists and its
 280      *             {@code checkListen} method doesn't allow the operation.
 281      *
 282      * @see SecurityManager#checkListen
 283      * @since   1.4
 284      */
 285     public DatagramSocket(SocketAddress bindaddr) throws SocketException {
 286         // Special case initialization for the DatagramChannel socket adaptor.
 287         if (this instanceof sun.nio.ch.DatagramSocketAdaptor) {
 288             this.impl = null;  // no DatagramSocketImpl
 289             this.oldImpl = false;
 290             return;
 291         }
 292 
 293         // create a datagram socket.
 294         boolean multicast = (this instanceof MulticastSocket);
 295         this.impl = createImpl(multicast);
 296         // creates the udp socket
 297         impl.create();
 298         created = true;
 299         this.oldImpl = checkOldImpl(impl);
 300         if (bindaddr != null) {
 301             try {
 302                 bind(bindaddr);
 303             } finally {
 304                 if (!isBound())
 305                     close();
 306             }
 307         }
 308     }
 309 
 310     /**
 311      * Constructs a datagram socket and binds it to the specified port
 312      * on the local host machine.  The socket will be bound to the


 346      *
 347      * @param port local port to use
 348      * @param laddr local address to bind
 349      *
 350      * @throws     SocketException  if the socket could not be opened,
 351      *               or the socket could not bind to the specified local port.
 352      * @throws     SecurityException  if a security manager exists and its
 353      *             {@code checkListen} method doesn't allow the operation.
 354      *
 355      * @see SecurityManager#checkListen
 356      * @since   1.1
 357      */
 358     public DatagramSocket(int port, InetAddress laddr) throws SocketException {
 359         this(new InetSocketAddress(laddr, port));
 360     }
 361 
 362     /**
 363      * Return true if the given DatagramSocketImpl is an "old" impl. An old impl
 364      * is one that doesn't implement the abstract methods added in Java SE 1.4.
 365      */
 366     private static boolean checkOldImpl(DatagramSocketImpl impl) {
 367         // DatagramSocketImpl.peekData() is a protected method, therefore we need to use
 368         // getDeclaredMethod, therefore we need permission to access the member
 369         try {
 370             AccessController.doPrivileged(
 371                 new PrivilegedExceptionAction<>() {
 372                     public Void run() throws NoSuchMethodException {
 373                         Class<?>[] cl = new Class<?>[1];
 374                         cl[0] = DatagramPacket.class;
 375                         impl.getClass().getDeclaredMethod("peekData", cl);
 376                         return null;
 377                     }
 378                 });
 379             return false;
 380         } catch (java.security.PrivilegedActionException e) {
 381             return true;
 382         }
 383     }
 384 
 385     static Class<?> implClass = null;
 386 
 387     /**
 388      * Creates a DatagramSocketImpl.
 389      * @param multicast true if the DatagramSocketImpl is for a MulticastSocket
 390      */

 391     private static DatagramSocketImpl createImpl(boolean multicast) throws SocketException {
 392         DatagramSocketImpl impl;
 393         DatagramSocketImplFactory factory = DatagramSocket.factory;
 394         if (factory != null) {
 395             impl = factory.createDatagramSocketImpl();
 396         } else {
 397             impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(multicast);
 398         }
 399         return impl;
 400     }
 401 
 402     /**
 403      * Return the {@code DatagramSocketImpl} attached to this socket,
 404      * creating the socket if not already created.
 405      *
 406      * @return  the {@code DatagramSocketImpl} attached to that
 407      *          DatagramSocket
 408      * @throws SocketException if creating the socket fails
 409      * @since 1.4
 410      */
 411     final DatagramSocketImpl getImpl() throws SocketException {
 412         if (!created) {
 413             synchronized (this) {
 414                 if (!created)  {
 415                     impl.create();
 416                     created = true;
 417                 }
 418             }
 419         }
 420         return impl;
 421     }
 422 
 423     /**
 424      * Binds this DatagramSocket to a specific address and port.
 425      * <p>
 426      * If the address is {@code null}, then the system will pick up
 427      * an ephemeral port and a valid local address to bind the socket.
 428      *
 429      * @param   addr The address and port to bind to.
 430      * @throws  SocketException if any error happens during the bind, or if the
 431      *          socket is already bound.


1486     private static Set<SocketOption<?>> options;
1487     private static boolean optionsSet = false;
1488 
1489     /**
1490      * Returns a set of the socket options supported by this socket.
1491      *
1492      * This method will continue to return the set of options even after
1493      * the socket has been closed.
1494      *
1495      * @return A set of the socket options supported by this socket. This set
1496      *        may be empty if the socket's DatagramSocketImpl cannot be created.
1497      *
1498      * @since 9
1499      */
1500     public Set<SocketOption<?>> supportedOptions() {
1501         synchronized(DatagramSocket.class) {
1502             if (optionsSet) {
1503                 return options;
1504             }
1505             try {
1506                 DatagramSocketImpl impl = getImpl();
1507                 options = Collections.unmodifiableSet(impl.supportedOptions());
1508             } catch (IOException e) {
1509                 options = Collections.emptySet();
1510             }
1511             optionsSet = true;
1512             return options;
1513         }
1514     }





















































1515 }


   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.FileDescriptor;
  29 import java.io.IOException;
  30 import java.io.UncheckedIOException;
  31 import java.nio.channels.DatagramChannel;
  32 import java.security.AccessController;
  33 import java.security.PrivilegedExceptionAction;
  34 import java.util.Objects;
  35 import java.util.Set;
  36 import java.util.Collections;
  37 
  38 /**
  39  * This class represents a socket for sending and receiving datagram packets.
  40  *
  41  * <p>A datagram socket is the sending or receiving point for a packet
  42  * delivery service. Each packet sent or received on a datagram socket
  43  * is individually addressed and routed. Multiple packets sent from
  44  * one machine to another may be routed differently, and may arrive in
  45  * any order.
  46  *
  47  * <p> Where possible, a newly constructed {@code DatagramSocket} has the
  48  * {@link StandardSocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as


 108  * can be useful when using a plain {@code DatagramSocket} to send datagrams to a
 109  * multicast group.
 110  *
 111  * @author  Pavani Diwanji
 112  * @see     java.net.DatagramPacket
 113  * @see     java.nio.channels.DatagramChannel
 114  * @since 1.0
 115  */
 116 public class DatagramSocket implements java.io.Closeable {
 117     /**
 118      * Various states of this socket.
 119      */
 120     private boolean bound = false;
 121     private boolean closed = false;
 122     private volatile boolean created;
 123     private final Object closeLock = new Object();
 124 
 125     /*
 126      * The implementation of this DatagramSocket.
 127      */
 128     @SuppressWarnings("deprecation")
 129     private final DatagramSocketImpl impl;
 130 
 131     /**
 132      * Are we using an older DatagramSocketImpl?
 133      */
 134     final boolean oldImpl;
 135 
 136     /**
 137      * Set when a socket is ST_CONNECTED until we are certain
 138      * that any packets which might have been received prior
 139      * to calling connect() but not read by the application
 140      * have been read. During this time we check the source
 141      * address of all packets received to be sure they are from
 142      * the connected destination. Other packets are read but
 143      * silently dropped.
 144      */
 145     private boolean explicitFilter = false;
 146     private int bytesLeftToFilter;
 147     /*
 148      * Connection state:


 237      *
 238      * @throws     SocketException  if the socket could not be opened,
 239      *               or the socket could not bind to the specified local port.
 240      * @throws     SecurityException  if a security manager exists and its
 241      *             {@code checkListen} method doesn't allow the operation.
 242      *
 243      * @see SecurityManager#checkListen
 244      */
 245     public DatagramSocket() throws SocketException {
 246         this(new InetSocketAddress(0));
 247     }
 248 
 249     /**
 250      * Creates an unbound datagram socket with the specified
 251      * DatagramSocketImpl.
 252      *
 253      * @param impl an instance of a <B>DatagramSocketImpl</B>
 254      *        the subclass wishes to use on the DatagramSocket.
 255      * @since   1.4
 256      */
 257     protected DatagramSocket(@SuppressWarnings("deprecation")DatagramSocketImpl impl) {
 258         if (impl == null)
 259             throw new NullPointerException();
 260         this.impl = impl;
 261         this.oldImpl = checkOldImpl(impl);
 262     }
 263 
 264     /**
 265      * Creates a datagram socket, bound to the specified local
 266      * socket address.
 267      * <p>
 268      * If, if the address is {@code null}, creates an unbound socket.
 269      *
 270      * <p>If there is a security manager,
 271      * its {@code checkListen} method is first called
 272      * with the port from the socket address
 273      * as its argument to ensure the operation is allowed.
 274      * This could result in a SecurityException.
 275      *
 276      * @param bindaddr local socket address to bind, or {@code null}
 277      *                 for an unbound socket.
 278      *
 279      * @throws     SocketException  if the socket could not be opened,
 280      *               or the socket could not bind to the specified local port.
 281      * @throws     SecurityException  if a security manager exists and its
 282      *             {@code checkListen} method doesn't allow the operation.
 283      *
 284      * @see SecurityManager#checkListen
 285      * @since   1.4
 286      */
 287     public DatagramSocket(SocketAddress bindaddr) throws SocketException {







 288         // create a datagram socket.
 289         boolean multicast = (this instanceof MulticastSocket);
 290         this.impl = createImpl(multicast);
 291         // creates the udp socket
 292         impl.create();
 293         created = true;
 294         this.oldImpl = checkOldImpl(impl);
 295         if (bindaddr != null) {
 296             try {
 297                 bind(bindaddr);
 298             } finally {
 299                 if (!isBound())
 300                     close();
 301             }
 302         }
 303     }
 304 
 305     /**
 306      * Constructs a datagram socket and binds it to the specified port
 307      * on the local host machine.  The socket will be bound to the


 341      *
 342      * @param port local port to use
 343      * @param laddr local address to bind
 344      *
 345      * @throws     SocketException  if the socket could not be opened,
 346      *               or the socket could not bind to the specified local port.
 347      * @throws     SecurityException  if a security manager exists and its
 348      *             {@code checkListen} method doesn't allow the operation.
 349      *
 350      * @see SecurityManager#checkListen
 351      * @since   1.1
 352      */
 353     public DatagramSocket(int port, InetAddress laddr) throws SocketException {
 354         this(new InetSocketAddress(laddr, port));
 355     }
 356 
 357     /**
 358      * Return true if the given DatagramSocketImpl is an "old" impl. An old impl
 359      * is one that doesn't implement the abstract methods added in Java SE 1.4.
 360      */
 361     private static boolean checkOldImpl(@SuppressWarnings("deprecation")DatagramSocketImpl impl) {
 362         // DatagramSocketImpl.peekData() is a protected method, therefore we need to use
 363         // getDeclaredMethod, therefore we need permission to access the member
 364         try {
 365             AccessController.doPrivileged(
 366                 new PrivilegedExceptionAction<>() {
 367                     public Void run() throws NoSuchMethodException {
 368                         Class<?>[] cl = new Class<?>[1];
 369                         cl[0] = DatagramPacket.class;
 370                         impl.getClass().getDeclaredMethod("peekData", cl);
 371                         return null;
 372                     }
 373                 });
 374             return false;
 375         } catch (java.security.PrivilegedActionException e) {
 376             return true;
 377         }
 378     }
 379 
 380     static Class<?> implClass = null;
 381 
 382     /**
 383      * Creates a DatagramSocketImpl.
 384      * @param multicast true if the DatagramSocketImpl is for a MulticastSocket
 385      */
 386     @SuppressWarnings("deprecation")
 387     private static DatagramSocketImpl createImpl(boolean multicast) throws SocketException {
 388         DatagramSocketImpl impl;
 389         DatagramSocketImplFactory factory = DatagramSocket.factory;
 390         if (factory != null) {
 391             impl = factory.createDatagramSocketImpl();
 392         } else {
 393             impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(multicast);
 394         }
 395         return impl;
 396     }
 397 
 398     /**
 399      * Return the {@code DatagramSocketImpl} attached to this socket,
 400      * creating the socket if not already created.
 401      *
 402      * @return  the {@code DatagramSocketImpl} attached to that
 403      *          DatagramSocket
 404      * @throws SocketException if creating the socket fails
 405      * @since 1.4
 406      */
 407     final @SuppressWarnings("deprecation")DatagramSocketImpl getImpl() throws SocketException {
 408         if (!created) {
 409             synchronized (this) {
 410                 if (!created)  {
 411                     impl.create();
 412                     created = true;
 413                 }
 414             }
 415         }
 416         return impl;
 417     }
 418 
 419     /**
 420      * Binds this DatagramSocket to a specific address and port.
 421      * <p>
 422      * If the address is {@code null}, then the system will pick up
 423      * an ephemeral port and a valid local address to bind the socket.
 424      *
 425      * @param   addr The address and port to bind to.
 426      * @throws  SocketException if any error happens during the bind, or if the
 427      *          socket is already bound.


1482     private static Set<SocketOption<?>> options;
1483     private static boolean optionsSet = false;
1484 
1485     /**
1486      * Returns a set of the socket options supported by this socket.
1487      *
1488      * This method will continue to return the set of options even after
1489      * the socket has been closed.
1490      *
1491      * @return A set of the socket options supported by this socket. This set
1492      *        may be empty if the socket's DatagramSocketImpl cannot be created.
1493      *
1494      * @since 9
1495      */
1496     public Set<SocketOption<?>> supportedOptions() {
1497         synchronized(DatagramSocket.class) {
1498             if (optionsSet) {
1499                 return options;
1500             }
1501             try {
1502                 @SuppressWarnings("deprecation")DatagramSocketImpl impl = getImpl();
1503                 options = Collections.unmodifiableSet(impl.supportedOptions());
1504             } catch (IOException e) {
1505                 options = Collections.emptySet();
1506             }
1507             optionsSet = true;
1508             return options;
1509         }
1510     }
1511 
1512     /**
1513      * An instance of a {@code DatagramSocketImpl} whose methods all throw an
1514      * {@UncheckedIOException}.
1515      *
1516      * <p> Suitable for use by subclasses of {@code DatagramSocket} and
1517      * {@code MulticastSocket}, that wish to provide their own <b>complete</b>
1518      * implementation, without delegating to the enclosing {@code impl} class.
1519      * For example:
1520      *
1521      * <pre>{@code
1522      * class CustomDatagramSocket extends DatagramSocket {
1523      *         CustomDatagramSocket() {
1524      *             super(DatagramSocket.THROWING_DGRM_IMPL);
1525      *         }
1526      *
1527      *         // override of all methods of DatagramSocket ...
1528      *     }
1529      * }</pre>
1530      */
1531     // TODO: find a better name
1532     @SuppressWarnings("deprecation")
1533     protected static final DatagramSocketImpl THROWING_DGRM_IMPL = new DatagramSocketImpl() {
1534         private final void throwUncheckedIOException() {
1535             throw new UncheckedIOException(new IOException("unimplemented"));
1536         }
1537         @Override protected void create()                              { throwUncheckedIOException();              }
1538         @Override protected void bind(int p, InetAddress a)            { throwUncheckedIOException();              }
1539         @Override protected void send(DatagramPacket p)                { throwUncheckedIOException();              }
1540         @Override protected void connect(InetAddress a, int p)         { throwUncheckedIOException();              }
1541         @Override protected void disconnect()                          { throwUncheckedIOException();              }
1542         @Override protected int getLocalPort()                         { throwUncheckedIOException(); return 0;    }
1543         @Override protected FileDescriptor getFileDescriptor()         { throwUncheckedIOException(); return null; }
1544         @Override protected int peek(InetAddress i)                    { throwUncheckedIOException(); return 0;    }
1545         @Override protected int peekData(DatagramPacket p)             { throwUncheckedIOException(); return 0;    }
1546         @Override protected void receive(DatagramPacket p)             { throwUncheckedIOException();              }
1547         @Override protected void setTTL(byte ttl)                      { throwUncheckedIOException();              }
1548         @Override protected byte getTTL()                              { throwUncheckedIOException(); return 0;    }
1549         @Override protected void setTimeToLive(int ttl)                { throwUncheckedIOException();              }
1550         @Override protected int getTimeToLive()                        { throwUncheckedIOException(); return 0;    }
1551         @Override protected void join(InetAddress a)                   { throwUncheckedIOException();              }
1552         @Override protected void leave(InetAddress a)                  { throwUncheckedIOException();              }
1553         @Override protected void joinGroup(SocketAddress a,
1554                                            NetworkInterface b)         { throwUncheckedIOException();              }
1555         @Override protected void leaveGroup(SocketAddress a,
1556                                             NetworkInterface b)        { throwUncheckedIOException();              }
1557         @Override protected void close()                               { throwUncheckedIOException();              }
1558         @Override public void setOption(int o, Object v)               { throwUncheckedIOException();              }
1559         @Override public Object getOption(int o)                       { throwUncheckedIOException(); return null; }
1560         @Override protected <T> void setOption(SocketOption<T> n, T v) { throwUncheckedIOException();              }
1561         @Override protected <T> T getOption(SocketOption<T> n)         { throwUncheckedIOException(); return null; }
1562         @Override protected Set<SocketOption<?>> supportedOptions()    { throwUncheckedIOException(); return null; }
1563     };
1564 }
< prev index next >