Handling multiple clients in Socket - java

I have developed a java swing client-server application. The server has many services like database service, cache service and client service talks to the clients.
The client service opens a socket on a port and listens to incoming connections. It spawns a new thread for every client connection, creates a session and reads the incoming serialized object. It maintains this session (keeps the thread alive) till the client issues a 'CLOSE_SESSION' command.
What i would like to know is if its correct to spawn a new thread for every new client-socket session. Thanks.
My client service code is as below.
Code to create server socket:
try {
ServerSocket socket = new ServerSocket(serverPort);
Socket listener = socket.accept();
Thread client = new Thread(new ClientHandler(listener));
client.start();
} catch (IOException ex) {
log.error(new Throwable(ex));
}
Code to spawn new thread for every client
class ClientHandler implements Runnable {
private static Logger log = Logger.getLogger(ClientHandler.class);
private Socket listener;
public ClientHandler(Socket listener) {
this.listener = listener;
}
public void run() {
try {
ObjectInputStream inStream = new ObjectInputStream(
listener.getInputStream());
try {
ServiceRequestResponse request = (ServiceRequestResponse) inStream
.readObject();
if (request != null && request.getServiceCommand() != null) {
ServiceCommand command = request.getServiceCommand();
log.debug("command : " + command.getCommand());
log.debug("is session alive? " + request.isAlive());
log.debug("ServiceCommand.CREATE_SESSION : "
+ ServiceCommand.CREATE_SESSION.getCommand());
if (!request.isAlive()
&& command.getCommand().equals(
ServiceCommand.CREATE_SESSION.getCommand())) {
// No session yet, and service command issued is login.
// Call login service, check credentials and create
// session.
request.setSessionId(UUID.randomUUID());
log.debug("Created user session with id : "
+ request.getSessionId());
} else {
if (command.getCommand().equals(
ServiceCommand.CLOSE_SESSION)) {
// Close session and do clean up here
}
// Here session is alive.
while (!ServiceCommand.CLOSE_SESSION.equals(command
.getCommand())) {
// Read the service command from the request
// response and
// Hand it over to the appropriate handler.
}
}
}
} catch (ClassNotFoundException ex) {
log.error(new Throwable(ex));
}
} catch (IOException ex) {
}
}
}

If your client session request can last long then thread-per-connection is a good solution.
Alternatives are:
Using NIO;
Using thread pool if client requests are short.

Related

Multi Thread Java Server

am currently working on a project where I have to build a multi thread server. I only started to work with threads so please understand me.
So far I have a class that implements the Runnable object, bellow you can see the code I have for the run method provided by the Runnable object.
public void run() {
while(true) {
try {
clientSocket = serversocket.accept();
for (int i = 0; i < 100; i++) {
DataOutputStream respond = new DataOutputStream(clientSocket.getOutputStream());
respond.writeUTF("Hello World! " + i);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
//
}
}
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
}
Bellow is the main method that creates a new object of the server class and creates a threat. initializing the Thread.
public static void main(String args[]) {
new Thread(new Server(1234, "", false)).start();
}
I know this creates a new thread but it does not serve multiple clients at once. The first client need to close the connection for the second to be served. How can I make a multi threated server that will serve different client sockets at once? Do I create the thread on the clientSocket = serverSocket.accept();
yes.
from the docs:
Supporting Multiple Clients
To keep the KnockKnockServer example simple, we designed it to listen for and handle a single connection request. However, multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads—one thread per each client connection.
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
The thread reads from and writes to the client connection as necessary.
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html

Java waiting for client's data pauses application cause of infinite loop

hey I am trying to make a console application that can receive and send messages to the clients.
It will accept multiple clients & handle them.
To add a new client i do this in the run method:
#Override
public void run() {
try {
this.server = new ServerSocket(this.port);
this.factory = new ServerFactory(this.server);
System.out.println("Server runs and now waiting for clients");
this.runClientHandler();
Socket client;
while ((client = this.server.accept()) != null) {
this.handler.addClient(this.factory.createClient(client));
System.out.println("done");
}
} catch (IOException e) {
e.printStackTrace();
}
}
But "done" will never be printed because of this client's infinite loop for his message:
public void handleClient() throws IOException {
byte[] buffer = new byte[5*1024];
int read = -1;
byte[] data;
String message;
while ((read = this.socket.getInputStream().read(buffer)) > -1) {
data = new byte[read];
System.arraycopy(buffer, 0, data, 0, read);
message = new String(data, "UTF-8");
System.out.println("Client message: " + message);
}
}
handleClient() method will run in Thread-2 at handleClients.add():
public void addClient(Client c) throws IOException {
c.writeMessageStream("hey");
System.out.println("New client!");
this.clients.add(c);
//prints here
c.handleClient();
//never reaches this..
}
How can I ignore the while loop and let the program execute while the while loop runs without making a new thread for each client?
Check NIO Selectors. They are part of Java NIO in JDK. Or you can use an out-of-the-box solutions like Netty or (worse) Apache MINA.
Your code won't be able to handle multiple clients as it is serving the client from the same thread it is accepting connections. Generally, the client connections should be handled by different threads and you may like to use asynchronous IO so that multiple connections can be handled from a single thread. You should use Netty which simplified all these. Here are some example programs http://netty.io/5.0/xref/io/netty/example/telnet/package-summary.html

Java SocketException. Why is it closed?

I'm trying to get a threaded chatserver working. But my socket is closing and I have no clue why it is.
In the server class I create a new ClientHandler
addHandler(new ClientHandler(this, incoming));
addHandler starts the thread and adds the new ClientHandler to an ArrayList in server.
incoming is the client socket.
public ClientHandler(Server serverArg, Socket sockArg) {
server = serverArg;
client = sockArg;
System.out.println(client.isClosed());
}
There is nothing called between
public void run() {
try {
System.out.println(client.isClosed());
in = new Scanner(client.getInputStream());
out = new PrintWriter(client.getOutputStream(), true);
announce();
System.out.println("Waiting for input");
boolean done = false;
while(!done && in.hasNextLine()) {
System.out.println("There is input!");
server.broadcast(clientName + ": " + in.nextLine());
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
When I run this code. This is the output:
false
true
java.net.SocketException: Socket is closed
Why is it closing immediately after creating this class / before starting it?
The connection is being closed by your code between when you add the handler and when the run() method is called. I suggest you add a breakpoint to the close method in the JDK and see where it is called. Or have a look at the code after you add the handler.
You can use a networking sniffer like wireshark or tcpdump.
To find out that if the connection broke due to the server side.
I guess that maybe the client side close the connection.

Access Class in different Threads

I'm building something here and I found myself in a pickle. Just some introduction first. I'm developing a client-server game. One of the functions it has is a chat that players can use to talk to another.
Player1 send a message to the server and the server forwards it to the respective Player2. My problemas is: how can I access classes from another thread so I can get the Socket object to relay the message to Player2.
while (listening)
{
try
{
//this is how I start a thread for each connection
//do I need to use identifiers or something?
new Client(serverSocket.accept()).start();
}
catch(IOException A)
{
reportError(A.toString()); //reportError is a function of mine
}
}
there are many ways to achieve this, the easiest would be:
public void start(){
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("Starting server on port: " + port);
while (serverState) {
Socket socket = ss.accept();
//stop server
if (!serverState) {
break;
}
Client handler = new Client(this, socket);
handler.start();
}
//when server is stopped, close all connections
for (Client client : clients.values()) {
client.closeConnection();
}
} catch (IOException e) {
}
}
if you send "this" inside the constructor of client and set it as a private variable you could Access it from the run function(other thread)

How to run multiple threads concurrently for Automated Selenium testing?

I have one web application from which I can start respective testing process which is in another Java app. I am using Socket Programming for communication between Web app and Java app.
When I request for specific process from web app then SocketServer from Java app hears request and start one thread for Testing process.
Testing process will initialize FirefoxDriver and start browser and do further test process.
My problem is, when I request for another process with different process name then It again creates second thread and start firefox browser but this time it is not considering my second process, it started to do same process which is first thread have.
I do not understand what to do...For every process I created a new thread but further it will doing same process.
My inputs are correctly received at Java app.
Please help me How can I do the concurrent thread safe processing?
I am using GWT,Java, Seleniun FirefoxDriver.
here is the Server code which is running in background and listen client request:
static final int PORT = 6789;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
InitializeApplication application = new InitializeApplication();
application.initialize();
serverSocket = new ServerSocket(PORT);
} catch (Exception e) {
log("Exception in SocketServerExecutor !!!",e);
}
while (true) {
try {
socket = serverSocket.accept();
} catch (Exception e) {
log("Exception in SocketServerExecutor !!!",e);
}
Thread thread = new Thread(new SocketServerThread(socket));
thread.start();
}
}
and this is the Thread which start process:
private Socket client;
public SocketServerThread(Socket serverSocket) {
this.client = serverSocket;
}
/**
* Starts appropriate process depending on process name from input.
* Input string contains:
* process name
*/
public void run() {
DataOutputStream outputStream = null;
String param = null;
try{
log("Just connected to "+ client.getRemoteSocketAddress());
try {
while ((param = in.readUTF()) != null){
log("got parameteres from client (i.e. from web app): "+param);
break;
}
} catch (Exception e) { }
if(param!=null && !param.isEmpty()){
String process = params[0];
ProcessManager manager = new ProcessManager();
if(process.equals("testUser"))
manager.startUserProcess(process);
else if(process.equals("testCustomer"))
manager.startCustomerProcess(process);
}
}catch(Exception exc){
if(exc instanceof SocketTimeoutException)
log("Socket timed out! [SocketServerThread]",exc);
else if(exc instanceof BindException)
log("BindException in SocketServerThread !!!",exc);
log(Level.SEVERE, "Exception in SocketServerThread !!!",exc);
}
}
and this is ProcessManager:
public void starUserProcess(String siteName) {
ExecutorService executerService = null;
try{
Callable<Object> callable = new ProcessThread(siteName);
executerService = Executors.newCachedThreadPool();
Future<Object> future = executerService.submit(callable);
future.get();
log("[ProcessManager] Process completed for "+process);
System.exit(0);
}catch (Exception e) {
log("[ProcessManager]::Exception");
log(ex);
}
}
ProcessThread will initialize all required things and Firefox browser and start process.
Client is new every time which contains input.
One of two things that I can thing of off the top of my head could be happening.
You are passing a paramater into your run() function that links back to the initial thread or...
You are using a shared variable that is accessible to all threads and the variable is either not being updated properly, or not being updated at all.
If you could include an SSCCE, that would help us determine where the problem truly lies.
Got the solution: I created the ExecutorService using newSingleThreadExecutor() instead of newCachedThreadPool() and also setDeamon(True) for every newly created ServerThread.
Here is the Executor documentation

Categories

Resources