I am trying to adapt my simple socket server so that it can have multiple TCP connections, via multithreading, but I can't seem to get it to work. My code so far is as follows, I'm not really sure where to go from here :

import java.net.*;
import java.io.*;

public class DoSomethingWithInput implements Runnable {
   private final Socket clientSocket; //initialize in const'r
   public void run() {


     BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String nextline;
        while ((nextline = in.readLine())!=null) {
           System.out.println(nextline);
        } //... close socket, etc.
    }
}


public class Socket{

  public Socket() {
}
@Override
public void run() {
  try {
    ServerSocket serverSocket = null;
    serverSocket = new ServerSocket(5432);
    for (;;) {
      ServerSocket serverSocket = null;
      serverSocket = new ServerSocket(5432);
      for (;;) {
        Socket clientSocket = null;
        clientSocket = serverSocket.accept();
        //delegate to new thread
        new Thread(new DoSomethingWithInput(clientSocket)).start();
      }
    }
  }catch (IOException e) {
   System.err.println("Could not listen on port: 5432.");
   System.exit(1);
}
}
}

Would anyone be able to give me some pointers on how I could do this, and why my current implementation will not work ? I was running through the tips in the Java tutorial http://download.oracle.com/javase/tutorial/networking/sockets/examples/KKMultiServerThread.java here, but the example they give here seems to use a lot of outside sources and classes like KnockKnockProtocol etc etc.

Would anyone be able to help me out with this?

Thank you very much!

Accepted Answer

The problem is that currently you're accepting the connection, but then immediately performing blocking reads on it until it's closed:

// After a few changes...
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
     clientSocket.getInputStream()));
String nextLine;
while ((nextLine = in.readLine()) != null) {
    System.out.println(nextline);
}

That means the same thread which accepts the connection is trying to handle the connection. That won't let you use multiple connections at the same time.

Instead, create a class (e.g. ConnectionHandler) which implements Runnable, and has a constructor taking a Socket. Its run method should handle the connection. Then change your code to:

Socket clientSocket = serverSocket.accept();
Runnable connectionHandler = new ConnectionHandler(clientSocket);
new Thread(connectionHandler).start();

That will leave your "main" thread free to wait for the next connection.

(By the way, the KnockKnockProtocol class isn't really "external" - it's part of the example. They just didn't make it very clear that the source is here...)

Written by Jon Skeet
This page was build to provide you fast access to the question and the direct accepted answer.
The content is written by members of the stackoverflow.com community.
It is licensed under cc-wiki