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!
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...)
You're not multithreading. You're creating a thread which binds on a port and then reads from any client socket until the connection is closed.
You need to pass the socket to a new thread and have it read.
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.
}
}
//...
ServerSocket serverSocket = null;
serverSocket = new ServerSocket(5432);
for (;;) {
Socket clientSocket = null;
clientSocket = serverSocket.accept();
//delegate to new thread
new Thread(new DoSomethingWithInput(clientSocket)).start();
} //...