0

I have the following server written which connects to a client:

ServerSocket server = null;

try
{
    server = new ServerSocket(4040);

    while (isServerListening)
    {
        Socket clientSocket = server.accept();

        // Send bytes to the Client
        ServerOutputStream = clientSocket.getOutputStream();

        byte[] bytes = "I am a Server".getBytes();
        ServerOutputStream.write(bytes);
    }
}
catch (IOException e)
{
    e.printStackTrace();
}
finally
{
    // close socket here
}

This server stops at line server.accept() and waits for next client to connect. At the same time I want to read messages received from client.

I did this socket programming via Event Handlers some years ago in different language but here it seems I will need a different approach.

My question is: Would I need another thread for this task? Is there an alternative e.g. non-blocking mode?

user963241
  • 6,758
  • 19
  • 65
  • 93

2 Answers2

1

My question is: Would I need another thread for this task?

One way of doing is to use a thread for each client connection. Application method runs the server in an infinite loop listening on the port. When a connection is requested, it spawns a new thread to do the servicing and immediately returns to listening.

ServerSocket listener = new ServerSocket(9898);
try {
    while (true) {
        new Handler(listener.accept(), clientNumber++).start();
    }
 } finally {
     listener.close();
 }

A thread to handle requests on a particular socket.

private static class Handler extends Thread {
    private Socket socket;
    private int clientNumber;

    public Handler(Socket socket, int clientNumber) {
        this.socket = socket;
        this.clientNumber = clientNumber;
    }

    public void run() {
        try {
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

            while (true) {
                String input = in.readLine();
                ...
            }
        } catch (IOException e) {
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                log("Couldn't close a socket, what's going on?");
            }
        }
    }
}

Is there an alternative e.g. non-blocking mode?

With non-blocking socket channels, server socket has to register with the selector to do certain operations. By default, a server socket channel is a blocking channel. To make it a non-blocking channel, set the following.

channel.configureBlocking(false);

The Non-blocking server program will look like ...

InetAddress hostIPAddress = InetAddress.getByName("localhost");
int port = 19000;
Selector selector = Selector.open();
ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(hostIPAddress, port));
channel.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
  Set keys = selector.selectedKeys();
  ...
}

The non-blocking Client program will look like ...

InetAddress serverIPAddress = InetAddress.getByName("localhost");
InetSocketAddress serverAddress = new InetSocketAddress(
    serverIPAddress, 19000);
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.connect(serverAddress);
int operations = SelectionKey.OP_CONNECT | SelectionKey.OP_READ
    | SelectionKey.OP_WRITE;
channel.register(selector, operations);

while (true) {
  if (selector.select() > 0) {
    Set keys = selector.selectedKeys();
    ...
  }
}
channel.close();
fabfas
  • 2,200
  • 1
  • 21
  • 21
0

You could create a thread pool and submit the clientSocket as new task to the ThreadPool

Socket clientSocket = serverSocket.accept();
threadPool.submit(new ClientTask(clientSocket)); 

You can find multiple implementations for multi-threaded server on the internet, check this one

ravthiru
  • 8,878
  • 2
  • 43
  • 52