/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
/*
* Created on Aug 18, 2005
*/
package org.jboss.test.remoting.transport.multiplex;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import org.jboss.remoting.transport.multiplex.MasterServerSocket;
import org.jboss.remoting.transport.multiplex.MultiplexingManager;
import org.jboss.remoting.transport.multiplex.VirtualServerSocket;
import org.jboss.remoting.transport.multiplex.VirtualServerSocketFactory;
import org.jboss.remoting.transport.multiplex.VirtualSocket;
/**
* A BasicServerSocketBehaviorClient.
* @author <a href="mailto:r.sigal@computer.org">Ron Sigal</a>
* @version $Revision: 1047 $
* <p>
* Copyright (c) 2005
* </p>
*/
public class BasicServerSocketBehaviorClient extends ShutdownClient implements MultiplexConstants
{
/***
* FIXME Comment this
*
*
*/
public void testPiggybackedVirtualServerSocket()
{
try
{
byte[] script = new byte[] {READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
CLOSE_TEST_SOCKET};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
VirtualServerSocket serverSocket = null;
int testSocketPort = testSocket.getLocalPort();
try
{
serverSocket = new VirtualServerSocket(testSocketPort);
assertTrue(doOneServerSocketTest(serverSocket, testSocketPort));
serverSocket.close();
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isClosed() == true);
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
try
{
// Give remote ServerSocket time to unregister.
InetSocketAddress address = new InetSocketAddress(serverSocket.getInetAddress(), serverSocket.getRemotePort());
log.warn("address: " + address);
while (MultiplexingManager.checkForShareableManager(address))
Thread.sleep(2000);
serverSocket = new VirtualServerSocket();
assertTrue(serverSocket.isBound() == false);
assertTrue(serverSocket.isClosed() == false);
// Bind serverSocket to the testSocket's local port. This will get the MultiplexingManager
// associated with testSocket, which is already connected
doBind(serverSocket, null, new InetSocketAddress(clientServerSocketHost, testSocketPort));
assertTrue(serverSocket.isBound() == true);
assertTrue(doOneServerSocketTest(serverSocket, testSocketPort));
serverSocket.close();
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isClosed() == true);
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
try
{
// Create a new VirtualServerSocket, and bind it to testSocket's local port.
// This will get the MultiplexingManager associated with testSocket, which is already connected
serverSocket = doBind(null,
basicBehaviorServerSocketAddress,
new InetSocketAddress(clientServerSocketHost, testSocketPort));
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isConnected() == true);
assertTrue(serverSocket.isClosed() == false);
assertTrue(doOneServerSocketTest(serverSocket, testSocketPort));
serverSocket.close();
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isConnected() == true);
assertTrue(serverSocket.isClosed() == true);
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testPiggybackedVirtualServerSocket() PASSES");
}
public void testIndependentVirtualServerSocket()
{
try
{
byte[] script = new byte[] {
ACCEPT_SERVER_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT_VSS,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
ACCEPT_SERVER_SOCKET,
READ, // make server wait until client's ServerSocket is up
WRITE,
CONNECT_TO_CLIENT_VSS,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
VirtualServerSocket serverSocket = null;
try
{
serverSocket = new VirtualServerSocket();
assertTrue(serverSocket.isBound() == false);
assertTrue(serverSocket.isClosed() == false);
// Bind serverSocket to an unused local address. This will lead to the creation of a new
// real socket, bound to that address, and a MultiplexingManager to wrap it.
log.info("binding to: " + nextBindPort);
doBind(serverSocket, null, new InetSocketAddress(clientServerSocketHost, nextBindPort));
assertTrue(serverSocket.isBound() == true);
// Connect serverSocket to a remote address. This will cause the real socket to connect to a
// MasterServerSocket at that address, leading to the creation of a real socket on the
// remote host and a MultiplexingManager to wrap it.
log.info("connecting server socket to port: " + ++nextConnectPort);
InetSocketAddress address1 = new InetSocketAddress(basicBehaviorServerHost, nextConnectPort);
is = testSocket.getInputStream();
is.read();
serverSocket.connect(address1);
assertTrue(serverSocket.isConnected());
assertTrue(doOneServerSocketTest(serverSocket, nextBindPort));
serverSocket.close();
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isClosed() == true);
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
try
{
// Create a new VirtualServerSocket, bind it to an unused local address, and connect it
// to the server. This will lead to the creation of a new real socket, wrapped by a MultiplexingManager,
// bound to that address and connected to the server.
nextBindPort++;
InetSocketAddress bindAddress = new InetSocketAddress(clientServerSocketHost, nextBindPort);
log.info("binding to: " + nextBindPort);
log.info("connecting server socket to port: " + ++nextConnectPort);
InetSocketAddress address2 = new InetSocketAddress(basicBehaviorServerHost, nextConnectPort);
is.read();
serverSocket = doBind(null, address2, bindAddress);
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isConnected() == true);
assertTrue(serverSocket.isClosed() == false);
assertTrue(doOneServerSocketTest(serverSocket, nextBindPort));
serverSocket.close();
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isConnected() == true);
assertTrue(serverSocket.isClosed() == true);
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testIndependentVirtualServerSocket() PASSES");
}
/**
* FIXME Comment this
*
*
*/
public void testMasterServerSocket()
{
try
{
byte[] script = new byte[] {READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT_MSS,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
MasterServerSocket serverSocket = null;
try
{
InetAddress bindAddress = InetAddress.getByName(clientServerSocketHost);
nextBindPort++;
log.info("binding to: " + nextBindPort);
serverSocket = new MasterServerSocket(nextBindPort, 50, bindAddress);
assertTrue(doOneServerSocketTest(serverSocket, nextBindPort));
serverSocket.close();
log.info("serverSocket bind address: " + serverSocket.getLocalPort());
log.info("serverSocket.isClosed(): " + serverSocket.isClosed());
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testMasterServerSocket() PASSES");
}
/**
* FIXME Comment this
*
*
*/
public void testServerSocketFactory()
{
log.info("entering testServerSocketFactory()");
try
{
byte[] script = new byte[]
{ ACCEPT_SERVER_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT_VSS,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT_MSS,
WRITE_TO_CLIENT,
READ_FROM_CLIENT,
CLOSE_CLIENT_SOCKET,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
try
{
VirtualServerSocketFactory serverSocketFactory
= (VirtualServerSocketFactory) VirtualServerSocketFactory.getDefault();
serverSocketFactory.setOnClient();
nextBindPort++;
log.info("binding to: " + nextBindPort);
InetAddress bindAddress = InetAddress.getByName(clientServerSocketHost);
VirtualServerSocket serverSocket
= (VirtualServerSocket) serverSocketFactory.createServerSocket(nextBindPort, 50, bindAddress);
log.info("connecting server socket to port: " + ++nextConnectPort);
InetSocketAddress address = new InetSocketAddress(basicBehaviorServerHost, nextConnectPort);
is = testSocket.getInputStream();
is.read();
serverSocket.connect(address);
assertTrue(doOneServerSocketTest(serverSocket, nextBindPort));
serverSocket.close();
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
try
{
VirtualServerSocketFactory serverSocketFactory
= (VirtualServerSocketFactory) VirtualServerSocketFactory.getDefault();
serverSocketFactory.setOnServer();
nextBindPort++;
log.info("binding to: " + nextBindPort);
InetAddress bindAddress = InetAddress.getByName(clientServerSocketHost);
MasterServerSocket serverSocket
= (MasterServerSocket) serverSocketFactory.createServerSocket(nextBindPort, 50, bindAddress);
assertTrue(doOneServerSocketTest(serverSocket, nextBindPort));
serverSocket.close();
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testServerSocketFactory() PASSES");
}
/**
* FIXME Comment this
*
*
*/
public void testConnectTimeout()
{
log.info("entering testConnectTimeout()");
try
{
byte[] script = new byte[]
{
RUN_SERVER_TIMEOUT_TEST,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
try
{
Socket socket1 = new VirtualSocket();
SocketAddress address1 = new InetSocketAddress(basicBehaviorServerHost, basicBehaviorServerPort + 100);
is = testSocket.getInputStream();
os = testSocket.getOutputStream();
is.read();
try
{
socket1.connect(address1, 200);
fail();
}
catch (SocketTimeoutException e)
{
if (e.getMessage().equals("connect timed out"))
log.info("received expected timeout exception");
else
fail();
}
while (!socket1.isClosed())
{
try
{
Thread.sleep(500);
log.error("waiting...");
}
catch (InterruptedException ignored) {}
}
try
{
socket1.connect(address1, 2000);
fail();
}
catch (SocketException e)
{
if (e.getMessage().equals("Socket is closed"))
log.info("received expected exception");
else
{
log.error(e);
fail();
}
}
Socket socket2 = new VirtualSocket();
socket2.connect(address1, 20000);
socket1.close();
socket2.close();
new Thread ()
{
public void run()
{
MasterServerSocket mss;
try
{
mss = new MasterServerSocket(clientServerSocketPort + 101);
log.info(mss.toString() + ": MasterServerSocket accepting");
os.write(3);
Socket s = mss.accept();
log.info(mss.toString() + ": accepted");
s.close();
mss.close();
}
catch (IOException e)
{
log.error(e);
}
}
}.start();
os = testSocket.getOutputStream();
Socket socket3 = new VirtualSocket();
SocketAddress address2 = new InetSocketAddress(basicBehaviorServerHost, basicBehaviorServerPort + 101);
is.read();
try
{
log.info("connecting to: " + address2);
log.info("shareable: " + MultiplexingManager.checkForShareableManager((InetSocketAddress)address2));
socket3.connect(address2, 400);
fail();
}
catch (SocketTimeoutException e)
{
if (e.getMessage().equals("connect timed out"))
log.info("received expected timeout exception");
else
fail();
}
try
{
socket3.connect(address1, 200);
fail();
}
catch (SocketException e)
{
if (e.getMessage().equals("Socket is closed"))
log.info("received expected exception");
else
{
log.error(e);
fail();
}
}
VirtualSocket socket4 = new VirtualSocket();
socket4.connect(address2, 20000);
// socket4.connect(address2);
socket3.close();
socket4.close();
}
catch(Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testConnectTimeout() PASSES");
}
public void testAcceptTimeout()
{
try
{
byte[] script = new byte[] {
ACCEPT_SERVER_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT_VSS,
CLOSE_CLIENT_SOCKET,
READ, // make server wait until client's ServerSocket is up
CONNECT_TO_CLIENT_MSS,
CLOSE_CLIENT_SOCKET,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
VirtualServerSocket serverSocket1 = null;
try
{
Socket virtualSocket1 = null;
Socket virtualSocket2 = null;
Socket virtualSocket3 = null;
Socket virtualSocket4 = null;
serverSocket1 = new VirtualServerSocket();
log.info("binding to: " + ++nextBindPort);
doBind(serverSocket1, null, new InetSocketAddress(clientServerSocketHost, nextBindPort));
log.info("connecting server socket to port: " + ++nextConnectPort);
InetSocketAddress address1 = new InetSocketAddress(basicBehaviorServerHost, nextConnectPort);
is = testSocket.getInputStream();
is.read();
serverSocket1.connect(address1);
serverSocket1.setSoTimeout(2000);
try
{
virtualSocket1 = serverSocket1.accept();
fail();
}
catch (SocketTimeoutException e)
{
if (e.getMessage().equals("Accept timed out"))
log.info("received expected timeout exception");
else
fail();
}
assertTrue(virtualSocket1 == null);
os = testSocket.getOutputStream();
os.write(3);
virtualSocket2 = serverSocket1.accept();
assertTrue(virtualSocket2.getSoTimeout() == 0);
virtualSocket2.close();
serverSocket1.close();
log.info("binding to: " + ++nextBindPort);
MasterServerSocket serverSocket2 = new MasterServerSocket(nextBindPort);
serverSocket2.setSoTimeout(2000);
try
{
virtualSocket3 = serverSocket2.accept();
fail();
}
catch (SocketTimeoutException e)
{
if (e.getMessage().equals("Accept timed out"))
log.info("received expected timeout exception");
else
fail();
}
assertTrue(virtualSocket3 == null);
os.write(5);
serverSocket2.setSoTimeout(20000);
virtualSocket4 = serverSocket2.accept();
assertTrue(virtualSocket4.getSoTimeout() == 0);
virtualSocket4.close();
serverSocket2.close();
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testAcceptTimeout() PASSES");
}
/**
* FIXME Comment this
*
*
*/
public void testVSS_to_VSS()
{
try
{
byte[] script = new byte[]
{
RUN_VSS_TO_VSS,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
VirtualServerSocket serverSocket = null;
try
{
serverSocket = new VirtualServerSocket();
log.info("binding to: " + ++nextBindPort);
doBind(serverSocket, null, new InetSocketAddress(clientServerSocketHost, nextBindPort));
log.info("connecting server socket to port: " + ++nextConnectPort);
InetSocketAddress address1 = new InetSocketAddress(basicBehaviorServerHost, nextConnectPort);
is = testSocket.getInputStream();
is.read();
serverSocket.connect(address1);
log.info("server socket is connected");
os = testSocket.getOutputStream();
os.write(5);
is.read();
int port = serverSocket.getRemotePort();
log.info("new virtual socket connecting to: " + port);
Socket virtualSocket1 = new VirtualSocket(clientServerSocketHost, port);
log.info("first virtual socket connected");
InputStream is1 = virtualSocket1.getInputStream();
OutputStream os1 = virtualSocket1.getOutputStream();
log.info("server socket accepting on port: " + serverSocket.getLocalPort());
Socket virtualSocket2 = serverSocket.accept();
log.info("second virtual socket created");
InputStream is2 = virtualSocket2.getInputStream();
OutputStream os2 = virtualSocket2.getOutputStream();
os1.write(9);
assertTrue(is1.read() == 9);
os2.write(11);
assertTrue(is2.read() == 11);
virtualSocket1.close();
virtualSocket2.close();
serverSocket.close();
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testVSS_to_VSS() PASSES");
}
class AcceptInterruptThread extends Thread
{
private ServerSocket ss;
private boolean success = false;
public AcceptInterruptThread(ServerSocket ss) {this.ss = ss;}
public boolean getSuccess() {return success;}
public void run()
{
try
{
log.info("now accepting on port: " + ss.getLocalPort());
ss.accept();
}
catch (Exception e)
{
if (e instanceof SocketException && e.getMessage().equals("Socket closed"))
success = true;
}
}
}
public void testAcceptInterrupt()
{
try
{
byte[] script = new byte[]
{
ACCEPT_SERVER_SOCKET,
WRITE,
READ,
CLOSE_TEST_SOCKET
};
scriptStream.write(script.length);
scriptStream.write(script);
}
catch (IOException e)
{
log.error(e);
}
try
{
VirtualServerSocket vss = new VirtualServerSocket();
log.info("binding to: " + ++nextBindPort);
BasicServerSocketBehaviorClient.doBind(vss, null, new InetSocketAddress(clientServerSocketHost, nextBindPort));
log.info("connecting server socket to port: " + ++nextConnectPort);
InetSocketAddress address1 = new InetSocketAddress(basicBehaviorServerHost, nextConnectPort);
is = testSocket.getInputStream();
is.read();
vss.connect(address1);
AcceptInterruptThread t1 = new AcceptInterruptThread(vss);
// Now that accept() is synchronized, only one thread can be in accept().
// AcceptInterruptThread t2 = new AcceptInterruptThread(vss);
t1.start();
// t2.start();
Thread.sleep(3000);
vss.close();
os = testSocket.getOutputStream();
os.write(7);
t1.join();
// t2.join();
assertTrue(t1.getSuccess());
// assertTrue(t2.getSuccess());
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
log.info("testAcceptInterrupt() PASSES");
}
/**
* FIXME Comment this
*
* @param serverSocket
* @param localPort
*/
protected boolean doOneServerSocketTest(final ServerSocket serverSocket, int localPort)
{
log.info("entering doOneServerSocketTest");
boolean success = true;
InetAddress clientServerSocket_Address = null;
InetSocketAddress clientServerSocket_SocketAddress = null;
try
{
clientServerSocket_Address = InetAddress.getByName(clientServerSocketHost);
clientServerSocket_SocketAddress = new InetSocketAddress(clientServerSocket_Address, localPort);
}
catch (UnknownHostException e)
{
log.error(e);
fail();
}
assertTrue(serverSocket.isBound() == true);
assertTrue(serverSocket.isClosed() == false);
assertTrue(serverSocket.getInetAddress().equals(clientServerSocket_Address));
assertTrue(serverSocket.getLocalSocketAddress().equals(clientServerSocket_SocketAddress));
assertTrue(serverSocket.getLocalPort() == localPort);
try
{
class StartSocketThread extends Thread
{
public VirtualSocket clientSocket;
public void run()
{
try
{
clientSocket = (VirtualSocket) serverSocket.accept();
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
}
}
}
StartSocketThread startSocketThread = new StartSocketThread();
startSocketThread.start();
os = testSocket.getOutputStream();
os.write(3); // server is waiting to read, after which it will connect
VirtualSocket clientSocket = startSocketThread.clientSocket;
while (clientSocket == null)
{
try
{
Thread.sleep(500);
}
catch (Exception e)
{
log.error(e);
}
clientSocket = startSocketThread.clientSocket;
}
log.info("VirtualServerSocket executed accept()");
InputStream is_client = clientSocket.getInputStream();
OutputStream os_client = clientSocket.getOutputStream();
int b = is_client.read();
os_client.write(b);
clientSocket.close();
serverSocket.close();
}
catch (IOException e)
{
log.error(e);
fail();
}
log.debug("leaving doOneServerSocketTest");
return success;
}
protected static VirtualServerSocket doBind(VirtualServerSocket serverSocket,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress)
{
log.info("entering doBind()");
log.info("serverSocket = " + serverSocket);
log.info("remote address: " + remoteAddress);
log.info("local address: " + localAddress);
VirtualServerSocket newServerSocket = null;
for (int i = 0; i < 5; i++)
{
try
{
if (serverSocket == null)
{
if (remoteAddress == null)
newServerSocket = new VirtualServerSocket(localAddress.getPort());
else
newServerSocket = new VirtualServerSocket(remoteAddress, localAddress, 0, null);
}
else
{
// ServerSockets created in testServerSocketFactory() may come in already bound.
if (!serverSocket.isBound())
serverSocket.bind(localAddress);
if (!serverSocket.isConnected() && remoteAddress != null)
serverSocket.connect(remoteAddress);
}
break;
}
catch (BindException e)
{
log.info("bind attempt failed: try again: " + e);
if (newServerSocket != null)
{
try
{
newServerSocket.close();
newServerSocket = null;
}
catch (IOException ignored)
{
log.error(e);
}
}
try
{
Thread.sleep(2000);
}
catch (InterruptedException ignored) {}
}
catch (SocketException e)
{
String message = e.getMessage();
if (message.equals("Already bound") || message.equals("Cannot assign requested address"))
{
log.info("bind attempt failed: try again");
log.info(e);
if (newServerSocket != null)
{
try
{
log.info("calling newServerSocket.close()");
newServerSocket.close();
newServerSocket = null;
}
catch (IOException ignored)
{
log.error(e);
}
}
try
{
Thread.sleep(2000);
}
catch (InterruptedException ignored) {}
}
else
{
log.error(e);
e.printStackTrace();
fail();
}
}
catch (Exception e)
{
log.error(e);
e.printStackTrace();
fail();
}
}
if (newServerSocket != null)
serverSocket = newServerSocket;
if (serverSocket == null || !serverSocket.isBound())
fail();
return serverSocket;
}
}