public void pickAddress() throws Exception {
if (publicAddress != null || bindAddress != null) {
return;
}
try {
final NetworkConfig networkConfig = node.getConfig().getNetworkConfig();
final AddressDefinition bindAddressDef = pickAddress(networkConfig);
final boolean reuseAddress = networkConfig.isReuseAddress();
final boolean bindAny = node.getGroupProperties().SOCKET_SERVER_BIND_ANY.getBoolean();
final int portCount = networkConfig.getPortCount();
log(Level.FINEST, "inet reuseAddress:" + reuseAddress);
InetSocketAddress inetSocketAddress;
ServerSocket serverSocket = null;
int port = networkConfig.getPort();
Throwable error = null;
for (int i = 0; i < portCount; i++) {
/**
* Instead of reusing the ServerSocket/ServerSocketChannel, we are going to close and replace them on
* every attempt to find a free port. The reason to do this is because in some cases, when concurrent
* threads/processes try to acquire the same port, the ServerSocket gets corrupted and isn't able to
* find any free port at all (no matter if there are more than enough free ports available). We have
* seen this happening on Linux and Windows environments.
*/
serverSocketChannel = ServerSocketChannel.open();
serverSocket = serverSocketChannel.socket();
serverSocket.setReuseAddress(reuseAddress);
serverSocket.setSoTimeout(1000);
try {
if (bindAny) {
inetSocketAddress = new InetSocketAddress(port);
} else {
inetSocketAddress = new InetSocketAddress(bindAddressDef.inetAddress, port);
}
log(Level.FINEST, "Trying to bind inet socket address:" + inetSocketAddress);
serverSocket.bind(inetSocketAddress, 100);
log(Level.FINEST, "Bind successful to inet socket address:" + inetSocketAddress);
break;
} catch (final Exception e) {
serverSocket.close();
serverSocketChannel.close();
if (networkConfig.isPortAutoIncrement()) {
port++;
error = e;
} else {
String msg = "Port [" + port + "] is already in use and auto-increment is "
+ "disabled. Hazelcast cannot start.";
logger.severe(msg, e);
throw new HazelcastException(msg, error);
}
}
}
if (serverSocket == null || !serverSocket.isBound()) {
throw new HazelcastException("ServerSocket bind has failed. Hazelcast cannot start! "
+ "config-port: " + networkConfig.getPort() + ", latest-port: " + port, error);
}
serverSocketChannel.configureBlocking(false);
bindAddress = createAddress(bindAddressDef, port);
log(Level.INFO, "Picked " + bindAddress + ", using socket " + serverSocket + ", bind any local is "
+ bindAny);