Multithreading / Multiple Connections
Hi all,
As part of my assessment I've got to make a client and server which can relay commands and responses between each other. I've managed to get everything working but I'd like to make it multi threaded and be able to accept multiple connections. How would I go about doing this?
At the moment when my client tries to connect on a port, its unable to because its in use. Can a server, once the socket is accepted, accept further connections on that socket? or does it have to create a socket on a new port. If it creates a socket on a new port, how does the client find the port ID?
These are all my questions and so far have got me incredibly confused, hopefully i'm over thinking this and there's some neat little class hiding around to solve all problems going. But we could only hope!
Ant
Re: Multithreading / Multiple Connections
The server should have a loop that contains the call to the accept() method. When the accept method returns with a socket connection to a client, it should create a new thread and pass that socket to the thread to process, and then loop back to the accept statement. The server would only use one port.
Re: Multithreading / Multiple Connections
Ah awesome, I sort of understand, i'll give it a go, thanks for the help!
Re: Multithreading / Multiple Connections
Hi again,
I've managed to get it to handle multiple connections however its not responding to the clients until all open clients have entered their command to the server.
ServerHandler
Code :
import java.net.*;
public class ServerHandler
{
int listeningPort = 6789;
int socketPort = 7000;
int maxConnections = 5;
ServerSocket welcomeSocket;
public ServerHandler()
{
while (true) {
checkForConnections();
}
}
public int checkForConnections() {
try {
welcomeSocket = new ServerSocket(listeningPort);
new Thread(new Server(socketPort, welcomeSocket)).start();
socketPort++;
return 1;
} catch (Exception e) {
}
return 0;
}
}
Server
Code :
import java.net.*;
import java.io.*;
public class Server implements Runnable
{
String clientMessage;
int serverPort;
ServerSocket welcomeSocket;
public Server(int port, ServerSocket socket)
{
this.serverPort = port;
welcomeSocket = socket;
}
public void run() {
try {
System.out.println("Server has been started on port: " + serverPort);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientMessage = inFromClient.readLine();
String response = checkCommand(clientMessage);
outToClient.writeBytes(response);
}
} catch (Exception e) {
}
}
public String checkCommand(String command) {
if (command.equals("hellothere")) {
return "hello" + "\n";
}
if (command.equals("CLOSE")) {
System.out.println(serverPort+": Server received the terminate command, shutting down.");
System.exit(0);
}
return "Command not found" + "\n";
}
}
Re: Multithreading / Multiple Connections
You should add a call to printStackTrace() to all of the catch blocks to show any errors that occur.
You should not ignore errors.
BTW Please use CODE tags not QUOTE tags around your code.
Re: Multithreading / Multiple Connections
Its not that its not working, its running fine with no errors. For some reason it just waits for all of the clients to send a command before responding.
Re: Multithreading / Multiple Connections
Try it with the printStackTrace calls to see if there are errors.
Re-read post#2
Re: Multithreading / Multiple Connections
Code :
java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:96)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:175)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at ServerHandler.checkForConnections(ServerHandler.java:19)
at ServerHandler.<init>(ServerHandler.java:13)
at StartServer.main(StartServer.java:4)
at __SHELL16.run(__SHELL16.java:6)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at bluej.runtime.ExecServer$3.run(ExecServer.java:724)
This is scrolling down the screen very fast
Re: Multithreading / Multiple Connections
Your forever while loop is calling a method that is causing the exception.
Re-read post#2
Re: Multithreading / Multiple Connections
Sorry to bug you again, I'm just unsure on how to do it
Re: Multithreading / Multiple Connections
I explained in post#2. What part of that is a problem for you?
Re: Multithreading / Multiple Connections
Well I'm not sure what you're getting at, the code I wrote and posted is how I interpreted what you've said.
Re: Multithreading / Multiple Connections
Your code did not put the call to accept() in the loop. Your loop called checkForConnections()
When accept() returned with a socket, your code does not create a new thread to handle the connection with that socket. It started processing the connection which would mean that no connections could be made to that socket until it finished.
Make a list of the steps the server should do in pseudo code and get the design down before writing the code.
Re: Multithreading / Multiple Connections
Thanks for all the help but I simply can't get this working, gonna go turn into the hulk now
Re: Multithreading / Multiple Connections
Have you worked out the logic in pseudo code yet? List the steps the code should do before writing the code.
Re: Multithreading / Multiple Connections
I understand it as follows:
Listens for a connection
Creates a thread and passes the socket
Think its a problem with my Server because its using the accept command as well and still using the Socket so it can't be used again.
Re: Multithreading / Multiple Connections
You need more details. For example where is the looping?
Re: Multithreading / Multiple Connections
while true
wait for a connection
connection found
create a thread
wait for a connection
....
That's what I expect it to do? I've never written pseudo code, I actually just Googled it and figured this is what you meant.
Is the problem not in here:
Code :
public void run() {
try {
System.out.println("Server has been started on port: " + serverPort);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientMessage = inFromClient.readLine();
String response = checkCommand(clientMessage);
outToClient.writeBytes(response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
This is the run() from my Server. Its still using the socket as its called the accept() so its still on that port.
Re: Multithreading / Multiple Connections
Quote:
while true
wait for a connection
connection found
create a thread
wait for a connection <<<<<<<<<<< Not needed already have at top of loop
Your steps are wrong. There should only be one waiting for connection in the loop.
define server socket
begin loop
wait for connection
get socket with connection
create thread and pass it the socket
end loop
Your code is wrong and needs a new design before writing any more code.
Re: Multithreading / Multiple Connections
Wow sweet I got it working, I realise what you meant now, I was getting confused with returning a ServerSocket and a Socket. I just read on the Oracle docs that accept() returns "Socket", changed my code in Server and it all works perfectly now.
Thanks for taking the time to help me (and not spoon feeding).
Re: Multithreading / Multiple Connections
Re: Multithreading / Multiple Connections
Thread-per-client approach is horrid. Stay away from the design if you are worrying about performance. It really depends on the task at hand, if you are looking for hundreds if not thousands of connections, a thread pool is a better route. If you are looking for only a handful of connections than it really doesn't matter. Just my two cents.