Summary
The API documentation of java.net.DatagramSocket
will be updated to clarify the behaviour of some of the APIs to match the current implementation.
Problem
DatagramSocket
class provides APIs for user applications to deal with UDP communication. connect(...)
is one such API which allows users to connect the underlying socket to a particular address so that the datagram sent from the socket will be delivered only to the connected address and datagrams from only that connected address will be received by this DatagramSocket
instance.
There are 2 connect(...)
methods on the DatagramSocket
:
public void connect(SocketAddress addr) throws SocketException
public void connect(InetAddress address, int port)
In the OpenJDK default implementation of these APIs, when the socket is already connected (through a prior call to either of these methods), then a subsequent call to connect(...)
will attempt to connect to the given address. This behaviour isn't currently specified.
Solution
The API documentation of these 2 methods will be updated to specify that the implementation will attempt to connect to the given address even when the socket is already connected. This clarification will match the current implementation in those methods.
While at it, the API documentation of some other methods of this class as well as the java.net.MulticastSocket
class have also been updated to provide clarity on what happens if those other methods are invoked when the socket is already closed. These clarifications too match the current implementation and are being done similar to what was done in https://bugs.openjdk.org/browse/JDK-8336868.
Specification
diff --git a/src/java.base/share/classes/java/net/DatagramSocket.java b/src/java.base/share/classes/java/net/DatagramSocket.java
index 9e94d1d8b6209..655b00bb8b6e1 100644
--- a/src/java.base/share/classes/java/net/DatagramSocket.java
+++ b/src/java.base/share/classes/java/net/DatagramSocket.java
@@ -395,7 +395,7 @@ public DatagramSocket(int port, InetAddress laddr) throws SocketException {
*
* @param addr The address and port to bind to.
* @throws SocketException if any error happens during the bind, or if the
- * socket is already bound.
+ * socket is already bound or is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @throws IllegalArgumentException if addr is a SocketAddress subclass
@@ -422,6 +422,11 @@ public void bind(SocketAddress addr) throws SocketException {
* call to send or receive may throw a PortUnreachableException. Note,
* there is no guarantee that the exception will be thrown.
*
+ * <p> If this socket is already connected, then this method will attempt to
+ * connect to the given address. If this connect fails then the state of
+ * this socket is unknown - it may or may not be connected to the address
+ * that it was previously connected to.
+ *
* <p> If a security manager has been installed then it is invoked to check
* access to the remote address. Specifically, if the given {@code address}
* is a {@link InetAddress#isMulticastAddress multicast address},
@@ -461,7 +466,7 @@ public void bind(SocketAddress addr) throws SocketException {
* not permit access to the given remote address
*
* @throws UncheckedIOException
- * may be thrown if connect fails, for example, if the
+ * if the port is 0 or connect fails, for example, if the
* destination address is non-routable
*
* @see #disconnect
@@ -484,6 +489,11 @@ public void connect(InetAddress address, int port) {
* have not been {@linkplain #receive(DatagramPacket) received} before invoking
* this method, may be discarded.
*
+ * <p> If this socket is already connected, then this method will attempt to
+ * connect to the given address. If this connect fails then the state of
+ * this socket is unknown - it may or may not be connected to the address
+ * that it was previously connected to.
+ *
* @param addr The remote address.
*
* @throws SocketException
@@ -643,7 +653,7 @@ public SocketAddress getLocalSocketAddress() {
*
* @param p the {@code DatagramPacket} to be sent.
*
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, or the socket is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} or {@code checkConnect}
* method doesn't allow the send.
@@ -702,7 +712,7 @@ public void send(DatagramPacket p) throws IOException {
*
* @param p the {@code DatagramPacket} into which to place
* the incoming data.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs, or the socket is closed.
* @throws SocketTimeoutException if setSoTimeout was previously called
* and the timeout has expired.
* @throws PortUnreachableException may be thrown if the socket is connected
@@ -770,7 +780,8 @@ public int getLocalPort() {
* operation to have effect.
*
* @param timeout the specified timeout in milliseconds.
- * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @throws IllegalArgumentException if {@code timeout} is negative
* @since 1.1
* @see #getSoTimeout()
@@ -784,7 +795,8 @@ public void setSoTimeout(int timeout) throws SocketException {
* option is disabled (i.e., timeout of infinity).
*
* @return the setting for SO_TIMEOUT
- * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @since 1.1
* @see #setSoTimeout(int)
*/
@@ -820,8 +832,8 @@ public int getSoTimeout() throws SocketException {
* @param size the size to which to set the send buffer
* size, in bytes. This value must be greater than 0.
*
- * @throws SocketException if there is an error
- * in the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @throws IllegalArgumentException if the value is 0 or is
* negative.
* @see #getSendBufferSize()
@@ -841,8 +853,8 @@ public void setSendBufferSize(int size) throws SocketException {
* getOption(StandardSocketOptions.SO_SNDBUF)}.
*
* @return the value of the SO_SNDBUF option for this {@code DatagramSocket}
- * @throws SocketException if there is an error in
- * the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @see #setSendBufferSize
* @see StandardSocketOptions#SO_SNDBUF
* @since 1.2
@@ -878,8 +890,8 @@ public int getSendBufferSize() throws SocketException {
* @param size the size to which to set the receive buffer
* size, in bytes. This value must be greater than 0.
*
- * @throws SocketException if there is an error in
- * the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @throws IllegalArgumentException if the value is 0 or is
* negative.
* @see #getReceiveBufferSize()
@@ -899,7 +911,8 @@ public void setReceiveBufferSize(int size) throws SocketException {
* getOption(StandardSocketOptions.SO_RCVBUF)}.
*
* @return the value of the SO_RCVBUF option for this {@code DatagramSocket}
- * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @see #setReceiveBufferSize(int)
* @see StandardSocketOptions#SO_RCVBUF
* @since 1.2
@@ -959,8 +972,8 @@ public void setReuseAddress(boolean on) throws SocketException {
* getOption(StandardSocketOptions.SO_REUSEADDR)}.
*
* @return a {@code boolean} indicating whether or not SO_REUSEADDR is enabled.
- * @throws SocketException if there is an error
- * in the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @since 1.4
* @see #setReuseAddress(boolean)
* @see StandardSocketOptions#SO_REUSEADDR
@@ -983,9 +996,8 @@ public boolean getReuseAddress() throws SocketException {
* @param on
* whether or not to have broadcast turned on.
*
- * @throws SocketException
- * if there is an error in the underlying protocol, such as an UDP
- * error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
*
* @since 1.4
* @see #getBroadcast()
@@ -1003,8 +1015,8 @@ public void setBroadcast(boolean on) throws SocketException {
* getOption(StandardSocketOptions.SO_BROADCAST)}.
*
* @return a {@code boolean} indicating whether or not SO_BROADCAST is enabled.
- * @throws SocketException if there is an error
- * in the underlying protocol, such as an UDP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as an UDP error, or the socket is closed.
* @since 1.4
* @see #setBroadcast(boolean)
* @see StandardSocketOptions#SO_BROADCAST
@@ -1049,8 +1061,8 @@ public boolean getBroadcast() throws SocketException {
* setOption(StandardSocketOptions.IP_TOS, tc)}.
*
* @param tc an {@code int} value for the bitset.
- * @throws SocketException if there is an error setting the
- * traffic class or type-of-service
+ * @throws SocketException if there is an error setting the traffic class or type-of-service,
+ * or the socket is closed.
* @since 1.4
* @see #getTrafficClass
* @see StandardSocketOptions#IP_TOS
@@ -1074,8 +1086,8 @@ public void setTrafficClass(int tc) throws SocketException {
* getOption(StandardSocketOptions.IP_TOS)}.
*
* @return the traffic class or type-of-service already set
- * @throws SocketException if there is an error obtaining the
- * traffic class or type-of-service value.
+ * @throws SocketException if there is an error obtaining the traffic class
+ * or type-of-service value, or the socket is closed.
* @since 1.4
* @see #setTrafficClass(int)
* @see StandardSocketOptions#IP_TOS
@@ -1092,6 +1104,9 @@ public int getTrafficClass() throws SocketException {
*
* <p> If this socket has an associated channel then the channel is closed
* as well.
+ *
+ * <p> Once closed, several of the methods defined by this class will throw
+ * an exception if invoked on the closed socket.
*/
public void close() {
delegate().close();
@@ -1299,7 +1314,7 @@ public Set<SocketOption<?>> supportedOptions() {
* datagram packets, or {@code null}.
* @throws IOException if there is an error joining, or when the address
* is not a multicast address, or the platform does not support
- * multicasting
+ * multicasting, or the socket is closed
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the join.
* @throws IllegalArgumentException if mcastaddr is {@code null} or is a
@@ -1343,7 +1358,7 @@ public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
* is unspecified: any interface may be selected or the operation
* may fail with a {@code SocketException}.
* @throws IOException if there is an error leaving or when the address
- * is not a multicast address.
+ * is not a multicast address, or the socket is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the operation.
* @throws IllegalArgumentException if mcastaddr is {@code null} or is a
diff --git a/src/java.base/share/classes/java/net/MulticastSocket.java b/src/java.base/share/classes/java/net/MulticastSocket.java
index 9a9d57118c0f1..46757a6b4077e 100644
--- a/src/java.base/share/classes/java/net/MulticastSocket.java
+++ b/src/java.base/share/classes/java/net/MulticastSocket.java
@@ -221,7 +221,7 @@ public MulticastSocket(SocketAddress bindaddr) throws IOException {
*
* @param ttl the time-to-live
* @throws IOException if an I/O exception occurs
- * while setting the default time-to-live value
+ * while setting the default time-to-live value, or the socket is closed.
* @deprecated use the {@link #setTimeToLive(int)} method instead, which uses
* <b>int</b> instead of <b>byte</b> as the type for ttl.
* @see #getTTL()
@@ -250,7 +250,7 @@ public void setTTL(byte ttl) throws IOException {
*
* @throws IOException
* if an I/O exception occurs while setting the
- * default time-to-live value
+ * default time-to-live value, or the socket is closed.
*
* @see #getTimeToLive()
* @see StandardSocketOptions#IP_MULTICAST_TTL
@@ -265,7 +265,7 @@ public void setTimeToLive(int ttl) throws IOException {
* the socket.
*
* @throws IOException if an I/O exception occurs
- * while getting the default time-to-live value
+ * while getting the default time-to-live value, or the socket is closed.
* @return the default time-to-live value
* @deprecated use the {@link #getTimeToLive()} method instead,
* which returns an <b>int</b> instead of a <b>byte</b>.
@@ -285,7 +285,7 @@ public byte getTTL() throws IOException {
* getOption(StandardSocketOptions.IP_MULTICAST_TTL)}.
*
* @throws IOException if an I/O exception occurs while
- * getting the default time-to-live value
+ * getting the default time-to-live value, or the socket is closed.
* @return the default time-to-live value
* @see #setTimeToLive(int)
* @see StandardSocketOptions#IP_MULTICAST_TTL
@@ -311,7 +311,7 @@ public int getTimeToLive() throws IOException {
* @param mcastaddr is the multicast address to join
* @throws IOException if there is an error joining,
* or when the address is not a multicast address,
- * or the platform does not support multicasting
+ * or the platform does not support multicasting, or the socket is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the join.
* @deprecated This method does not accept the network interface on
@@ -339,7 +339,7 @@ public void joinGroup(InetAddress mcastaddr) throws IOException {
*
* @param mcastaddr is the multicast address to leave
* @throws IOException if there is an error leaving
- * or when the address is not a multicast address.
+ * or when the address is not a multicast address, or the socket is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} method doesn't allow the operation.
* @deprecated This method does not accept the network interface on which
@@ -393,7 +393,7 @@ public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
*
* @param inf the InetAddress
* @throws SocketException if there is an error in
- * the underlying protocol, such as a TCP error.
+ * the underlying protocol, such as a TCP error, or the socket is closed.
* @deprecated The InetAddress may not uniquely identify
* the network interface. Use
* {@link #setNetworkInterface(NetworkInterface)} instead.
@@ -413,7 +413,7 @@ public void setInterface(InetAddress inf) throws SocketException {
* or if no interface has been set, an {@code InetAddress}
* representing any local address.
* @throws SocketException if there is an error in the
- * underlying protocol, such as a TCP error.
+ * underlying protocol, such as a TCP error, or the socket is closed.
* @deprecated The network interface may not be uniquely identified by
* the InetAddress returned.
* Use {@link #getNetworkInterface()} instead.
@@ -434,7 +434,7 @@ public InetAddress getInterface() throws SocketException {
*
* @param netIf the interface
* @throws SocketException if there is an error in
- * the underlying protocol, such as a TCP error.
+ * the underlying protocol, such as a TCP error, or the socket is closed.
* @see #getNetworkInterface()
* @see StandardSocketOptions#IP_MULTICAST_IF
* @since 1.4
@@ -454,7 +454,7 @@ public void setNetworkInterface(NetworkInterface netIf)
* getOption(StandardSocketOptions.IP_MULTICAST_IF)}.
*
* @throws SocketException if there is an error in
- * the underlying protocol, such as a TCP error.
+ * the underlying protocol, such as a TCP error, or the socket is closed.
* @return The multicast {@code NetworkInterface} currently set. A placeholder
* NetworkInterface is returned when there is no interface set; it has
* a single InetAddress to represent any local address.
@@ -476,7 +476,8 @@ public NetworkInterface getNetworkInterface() throws SocketException {
* verify what loopback mode is set to should call
* {@link #getLoopbackMode()}
* @param disable {@code true} to disable the LoopbackMode
- * @throws SocketException if an error occurs while setting the value
+ * @throws SocketException if an error occurs while setting the value, or
+ * the socket is closed.
* @since 1.4
* @deprecated Use {@link #setOption(SocketOption, Object)} with
* {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP}
@@ -493,7 +494,8 @@ public void setLoopbackMode(boolean disable) throws SocketException {
/**
* Get the setting for local loopback of multicast datagrams.
*
- * @throws SocketException if an error occurs while getting the value
+ * @throws SocketException if an error occurs while getting the value, or
+ * the socket is closed.
* @return true if the LoopbackMode has been disabled
* @since 1.4
* @deprecated Use {@link #getOption(SocketOption)} with
@@ -534,8 +536,7 @@ public boolean getLoopbackMode() throws SocketException {
* @param ttl optional time to live for multicast packet.
* default ttl is 1.
*
- * @throws IOException is raised if an error occurs i.e
- * error while setting ttl.
+ * @throws IOException if an I/O error occurs, or the socket is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkMulticast} or {@code checkConnect}
* method doesn't allow the send.
- csr of
-
JDK-8336817 Several methods on DatagramSocket and MulticastSocket do not specify behaviour when already closed or connected
-
- Resolved
-