/*
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.net;

import java.net.*;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import jdk.net.ExtendedSocketOptions.PlatformSocketOptions;

Defines static methods to set and get socket options defined by the SocketOption interface. All of the standard options defined by Socket, ServerSocket, and DatagramSocket can be set this way, as well as additional or platform specific options supported by each socket type.

The supportedOptions(Class<?>) method can be called to determine the complete set of options available (per socket type) on the current system.

When a security manager is installed, some non-standard socket options may require a security permission before being set or get. The details are specified in ExtendedSocketOptions. No permission is required for StandardSocketOptions.

See Also:
/** * Defines static methods to set and get socket options defined by the * {@link java.net.SocketOption} interface. All of the standard options defined * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and * {@link java.net.DatagramSocket} can be set this way, as well as additional * or platform specific options supported by each socket type. * <p> * The {@link #supportedOptions(Class)} method can be called to determine * the complete set of options available (per socket type) on the * current system. * <p> * When a security manager is installed, some non-standard socket options * may require a security permission before being set or get. * The details are specified in {@link ExtendedSocketOptions}. No permission * is required for {@link java.net.StandardSocketOptions}. * * @see java.nio.channels.NetworkChannel */
public class Sockets { private static final Map<Class<?>,Set<SocketOption<?>>> options = optionSets(); private Sockets() {}
Sets the value of a socket option on a Socket
Params:
  • s – the socket
  • name – The socket option
  • value – The value of the socket option. May be null for some options.
Throws:
See Also:
/** * Sets the value of a socket option on a {@link java.net.Socket} * * @param s the socket * @param name The socket option * @param value The value of the socket option. May be null for some * options. * * @throws UnsupportedOperationException if the socket does not support * the option. * * @throws IllegalArgumentException if the value is not valid for * the option. * * @throws IOException if an I/O error occurs, or socket is closed. * * @throws SecurityException if a security manager is set and the * caller does not have any required permission. * * @throws NullPointerException if name is null * * @see java.net.StandardSocketOptions */
public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException { s.setOption(name, value); }
Returns the value of a socket option from a Socket
Params:
  • s – the socket
  • name – The socket option
Throws:
See Also:
Returns:The value of the socket option.
/** * Returns the value of a socket option from a {@link java.net.Socket} * * @param s the socket * @param name The socket option * * @return The value of the socket option. * * @throws UnsupportedOperationException if the socket does not support * the option. * * @throws IOException if an I/O error occurs * * @throws SecurityException if a security manager is set and the * caller does not have any required permission. * * @throws NullPointerException if name is null * * @see java.net.StandardSocketOptions */
public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException { return s.getOption(name); }
Sets the value of a socket option on a ServerSocket
Params:
  • s – the socket
  • name – The socket option
  • value – The value of the socket option.
Throws:
See Also:
/** * Sets the value of a socket option on a {@link java.net.ServerSocket} * * @param s the socket * @param name The socket option * @param value The value of the socket option. * * @throws UnsupportedOperationException if the socket does not support * the option. * * @throws IllegalArgumentException if the value is not valid for * the option. * * @throws IOException if an I/O error occurs * * @throws NullPointerException if name is null * * @throws SecurityException if a security manager is set and the * caller does not have any required permission. * * @see java.net.StandardSocketOptions */
public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException { s.setOption(name, value); }
Returns the value of a socket option from a ServerSocket
Params:
  • s – the socket
  • name – The socket option
Throws:
See Also:
Returns:The value of the socket option.
/** * Returns the value of a socket option from a {@link java.net.ServerSocket} * * @param s the socket * @param name The socket option * * @return The value of the socket option. * * @throws UnsupportedOperationException if the socket does not support * the option. * * @throws IOException if an I/O error occurs * * @throws NullPointerException if name is null * * @throws SecurityException if a security manager is set and the * caller does not have any required permission. * * @see java.net.StandardSocketOptions */
public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException { return s.getOption(name); }
Sets the value of a socket option on a DatagramSocket or MulticastSocket
Params:
  • s – the socket
  • name – The socket option
  • value – The value of the socket option.
Throws:
See Also:
/** * Sets the value of a socket option on a {@link java.net.DatagramSocket} * or {@link java.net.MulticastSocket} * * @param s the socket * @param name The socket option * @param value The value of the socket option. * * @throws UnsupportedOperationException if the socket does not support * the option. * * @throws IllegalArgumentException if the value is not valid for * the option. * * @throws IOException if an I/O error occurs * * @throws NullPointerException if name is null * * @throws SecurityException if a security manager is set and the * caller does not have any required permission. * * @see java.net.StandardSocketOptions */
public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException { s.setOption(name, value); }
Returns the value of a socket option from a DatagramSocket or MulticastSocket
Params:
  • s – the socket
  • name – The socket option
Throws:
See Also:
Returns:The value of the socket option.
/** * Returns the value of a socket option from a * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket} * * @param s the socket * @param name The socket option * * @return The value of the socket option. * * @throws UnsupportedOperationException if the socket does not support * the option. * * @throws IOException if an I/O error occurs * * @throws NullPointerException if name is null * * @throws SecurityException if a security manager is set and the * caller does not have any required permission. * * @see java.net.StandardSocketOptions */
public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException { return s.getOption(name); }
Returns a set of SocketOptions supported by the given socket type. This set may include standard options and also non standard extended options.
Params:
  • socketType – the type of java.net socket
Throws:
/** * Returns a set of {@link java.net.SocketOption}s supported by the * given socket type. This set may include standard options and also * non standard extended options. * * @param socketType the type of java.net socket * * @throws IllegalArgumentException if socketType is not a valid * socket type from the java.net package. */
public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) { Set<SocketOption<?>> set = options.get(socketType); if (set == null) { throw new IllegalArgumentException("unknown socket type"); } return set; } private static void checkValueType(Object value, Class<?> type) { if (!type.isAssignableFrom(value.getClass())) { String s = "Found: " + value.getClass().toString() + " Expected: " + type.toString(); throw new IllegalArgumentException(s); } } private static volatile boolean checkedReusePort; private static volatile boolean isReusePortAvailable;
Tells whether SO_REUSEPORT is supported.
/** * Tells whether SO_REUSEPORT is supported. */
static boolean isReusePortAvailable() { if (!checkedReusePort) { Set<SocketOption<?>> s = new Socket().supportedOptions(); isReusePortAvailable = s.contains(StandardSocketOptions.SO_REUSEPORT); checkedReusePort = true; } return isReusePortAvailable; } private static Map<Class<?>,Set<SocketOption<?>>> optionSets() { Map<Class<?>,Set<SocketOption<?>>> options = new HashMap<>(); boolean flowsupported = PlatformSocketOptions.get().flowSupported(); boolean reuseportsupported = isReusePortAvailable(); // Socket Set<SocketOption<?>> set = new HashSet<>(); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); if (reuseportsupported) { set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.TCP_NODELAY); if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); } if (QuickAck.available) { set.add(ExtendedSocketOptions.TCP_QUICKACK); } if (KeepAliveOptions.AVAILABLE) { set.addAll(Set.of(ExtendedSocketOptions.TCP_KEEPCOUNT, ExtendedSocketOptions.TCP_KEEPIDLE, ExtendedSocketOptions.TCP_KEEPINTERVAL)); } set = Collections.unmodifiableSet(set); options.put(Socket.class, set); // ServerSocket set = new HashSet<>(); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); if (reuseportsupported) { set.add(StandardSocketOptions.SO_REUSEPORT); } if (QuickAck.available) { set.add(ExtendedSocketOptions.TCP_QUICKACK); } if (KeepAliveOptions.AVAILABLE) { set.addAll(Set.of(ExtendedSocketOptions.TCP_KEEPCOUNT, ExtendedSocketOptions.TCP_KEEPIDLE, ExtendedSocketOptions.TCP_KEEPINTERVAL)); } set.add(StandardSocketOptions.IP_TOS); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); // DatagramSocket set = new HashSet<>(); set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); if (reuseportsupported) { set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.IP_TOS); if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); } set = Collections.unmodifiableSet(set); options.put(DatagramSocket.class, set); // MulticastSocket set = new HashSet<>(); set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); if (reuseportsupported) { set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); } set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); return Collections.unmodifiableMap(options); }
Tells whether TCP_QUICKACK is supported.
/** * Tells whether TCP_QUICKACK is supported. */
static class QuickAck { static final boolean available; static { Set<SocketOption<?>> s = new Socket().supportedOptions(); available = s.contains(ExtendedSocketOptions.TCP_QUICKACK); } }
Tells whether TCP_KEEPALIVE options are supported.
/** * Tells whether TCP_KEEPALIVE options are supported. */
static class KeepAliveOptions { static final boolean AVAILABLE; static { Set<SocketOption<?>> s = new Socket().supportedOptions(); AVAILABLE = s.containsAll(Set.of(ExtendedSocketOptions.TCP_KEEPCOUNT, ExtendedSocketOptions.TCP_KEEPIDLE, ExtendedSocketOptions.TCP_KEEPINTERVAL)); } } }