com.sun.grizzly.PortRange Maven / Gradle / Ivy
package com.sun.grizzly;
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* Immutable class representing a port range.
* @author: Gerd Behrmann
* @author: Tigran Mkrtchyan
*/
public class PortRange
{
/** Pattern matching [:] */
private final static Pattern FORMAT =
Pattern.compile("(\\d+)(?:(?:,|:)(\\d+))?");
private final int lower;
private final int upper;
/**
* Random number generator used when binding sockets.
*/
private final static Random _random = new Random();
/**
* Creates a port range with the given bounds (both inclusive).
*
* @throws IllegalArgumentException is either bound is not between
* 0 and 65535, or if high is lower than
* low.
*/
public PortRange(int low, int high)
{
if (low < 0 || high < low || 65535 < high) {
throw new IllegalArgumentException("Invalid range");
}
lower = low;
upper = high;
}
/**
* Creates a port range containing a single port.
*/
public PortRange(int port)
{
this(port, port);
}
/**
* Parse a port range. A port range consists of either a single
* integer, or two integers separated by either a comma or a
* colon.
*
* The bounds must be between 0 and 65535, both inclusive.
*
* @return The port range represented by s. Returns
* the range [0,0] if s is null or empty.
*/
public static PortRange valueOf(String s)
throws IllegalArgumentException
{
try {
Matcher m = FORMAT.matcher(s);
if (!m.matches()) {
throw new IllegalArgumentException("Invalid range: " + s);
}
int low = Integer.parseInt(m.group(1));
int high =
(m.groupCount() == 1) ? low : Integer.parseInt(m.group(2));
return new PortRange(low, high);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid range: " + s);
}
}
/**
* Returns a random port within the range.
*/
public int random()
{
return _random.nextInt(upper - lower + 1) + lower;
}
/**
* Returns the successor of a port within the range, wrapping
* around to the lowest port if necessary.
*/
public int succ(int port)
{
return (port < upper ? port + 1 : (int) lower);
}
public int getLower() {
return lower;
}
public int getUpper() {
return upper;
}
/**
* Binds socket to endpoint. If the
* port in endpoint is zero, then a port is chosen
* from this port range. If the port range is [0,0], then a free
* port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(ServerSocket socket, InetSocketAddress endpoint, int backLog)
throws IOException
{
int port = endpoint.getPort();
PortRange range = (port > 0) ? new PortRange(port) : this;
range.bind(socket, endpoint.getAddress(), backLog);
}
/**
* Binds socket to endpoint. If the
* port in endpoint is zero, then a port is chosen
* from this port range. If the port range is [0,0], then a free
* port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(Socket socket, InetSocketAddress endpoint)
throws IOException
{
int port = endpoint.getPort();
PortRange range = (port > 0) ? new PortRange(port) : this;
range.bind(socket, endpoint.getAddress());
}
/**
* Binds socket to address. A port is
* chosen from this port range. If the port range is [0,0], then a
* free port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(ServerSocket socket, InetAddress address, int backLog)
throws IOException
{
int start = random();
int port = start;
do {
try {
socket.bind(new InetSocketAddress(address, port), backLog);
return;
} catch (BindException e) {
}
port = succ(port);
} while (port != start);
throw new BindException("No free port within range");
}
/**
* Binds socket to address. A port is
* chosen from this port range. If the port range is [0,0], then a
* free port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(Socket socket, InetAddress address)
throws IOException
{
int start = random();
int port = start;
do {
try {
socket.bind(new InetSocketAddress(address, port));
return;
} catch (BindException e) {
}
port = succ(port);
} while (port != start);
throw new BindException("No free port within range");
}
/**
* Binds socket to address. A port is
* chosen from this port range. If the port range is [0,0], then a
* free port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(DatagramSocket socket, InetAddress address)
throws IOException {
int start = random();
int port = start;
do {
try {
socket.bind(new InetSocketAddress(address, port));
return;
} catch (BindException e) {
}
port = succ(port);
} while (port != start);
throw new BindException("No free port within range");
}
/**
* Binds socket to the wildcard
* address. A port is chosen from this port range. If
* the port range is [0,0], then a free port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(DatagramSocket socket)
throws IOException {
bind(socket, (InetAddress) null);
}
/**
* Binds socket to the wildcard
* address. A port is chosen from this port range. If
* the port range is [0,0], then a free port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(ServerSocket socket, int backLog)
throws IOException
{
bind(socket, (InetAddress) null, 50);
}
/**
* Binds socket to the wildcard
* address. A port is chosen from this port range. If
* the port range is [0,0], then a free port is chosen by the OS.
*
* @throws IOException if the bind operation fails, or if the
* socket is already bound.
*/
public void bind(Socket socket)
throws IOException
{
bind(socket, (InetAddress) null);
}
@Override
public String toString()
{
return String.format("%d:%d", lower, upper);
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy