Multithread Server Java - java

I'm trying to make a simple ECHO server that can manage more client.
Server Class:
public class EchoServer {
protected int port ;
protected ServerSocket socket;
private Socket acceptedSocket;
public EchoServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
}
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket = socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
}
Runnable client handler:
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter From_Server = null;
BufferedReader To_Server = null;
String to_server_string = null;
try {
From_Server = new PrintWriter(socket.getOutputStream());
To_Server =
new BufferedReader(
new InputStreamReader( socket.getInputStream()));
System.out.println("Stream opened.\n");
while(true) {
if(To_Server.ready()){
System.out.println("Reading input line.\n");
to_server_string = To_Server.readLine();
if(to_server_string.equalsIgnoreCase("quit")) {
System.out.println("Connection closed on user request.\n");
From_Server.print("Bye :)\n");
From_Server.close();
To_Server.close();
socket.close();
}
else {
System.out.println(
"String '" +
to_server_string+"' is not 'quit', echoing.\n");
From_Server.print("ECHO: "+to_server_string+"\n");
System.out.println("String written on stream, flushing.\n");
From_Server.flush();
}
}
}
}
catch (IOException e) {
System.out.println("Stream error (connection closed?).\n");
}
}
}
Main Class
public static void main(String[] args) {
try {
EchoServer server= new EchoServer(9999);
server.start();
}
catch (IOException ex) {
System.out.println("Unable to start server (port is busy?)\n");
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (AcceptingClientException e){
System.out.println("Unable to accept client\n");
}
}
More than one client is able to connect to the server, but the ECHO will works only with one client at the time (if I close the connection with one client the server will start to handle another one automatically), but I can't understand why: when a client connects to the server, the associated socked created with server.accept() is passed to a new instance of a runnable client handler which is started with handler.run() and the server should go back on waiting in server.accept() (unless the ServerSocket is closed).
I'm assuming the issue should be with this method of the server class:
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket=socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
But I can't figure out what is wrong with it...what am I missing?

Your code:
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
doesn't start a new thread, it delegates to ClientHandler.run() in the same thread.
To start a thread, use new Thread( ch ).start(); since ch is of class ClientHandler which implements Runnable.

Related

How to run two instances of java socket servers listenening on two different ports?

Scenario:
a) Persistent connections
b) Manage each server-client communication individually
c) Protect System from propagating exceptions/errors
I tried to created two instances of server socket listeners using the following code :
SimpleSocketServers.java
public class SimpleSocketServers {
public static void main(String[] args) throws Exception {
int port1 = 9876;
SimpleSocketServer server1 = new SimpleSocketServer(port1);
server1.startAndRunServer();
System.out.println("Servers : server1 Listening on port: " + port1);
int port2 = 9875;
SimpleSocketServer server2 = new SimpleSocketServer(port2);
server2.startAndRunServer();
System.out.println("Servers : server2 Listening on port: " + port2);
}
}
and
SimpleSocketServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleSocketServer {
private ServerSocket serverSocket;
private int port;
public SimpleSocketServer(int port) {
this.port = port;
}
public void startAndRunServer() {
try {
System.out.println("Starting Server at port " + port + " ...");
serverSocket = new ServerSocket(port);
System.out.println("Listening for client connection ...");
Socket socket = serverSocket.accept();
RequestHandler requestHandler = new RequestHandler(socket);
requestHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class RequestHandler extends Thread {
private Socket socket;
RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Client Request Response being processed...");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
But, it creates only one instance as control is not returning from the constructor of first instance. Is there any possibility to get back control and run both instances of server socket listeners simultaneously? (ps: Pardon me, if it is wrong or trivial!)
Use 2 Different Threads, Listening To 2 Different Ports.
Thread ServerThread1 = new Thread(new Runnable() {
#Override
public void run() {
ServerSocket ServerSocketObject = null;
while(true)
{
try {
ServerSocketObject = new ServerSocket(Your_Port_Number1);
Socket SocketObject = ServerSocketObject.accept();
// Your Code Here
SocketObject.close();
} catch (IOException e) {
try {
ServerSocketObject.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
});
Thread ServerThread2 = new Thread(new Runnable() {
#Override
public void run() {
ServerSocket ServerSocketObject = null;
while(true)
{
try {
ServerSocketObject = new ServerSocket(Your_Port_Number2);
Socket SocketObject = ServerSocketObject.accept();
// Your Code Here
SocketObject.close();
} catch (IOException e) {
try {
ServerSocketObject.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
});
ServerThread1.start();
ServerThread2.start();
You need to have SimpleSocketServer implement Runnable; start a thread with itself as the Runnable in the constructor; and run an accept() loop in the run() method. At present you're blocking in the constructor waiting for a connection, and your servers will also only handle a single connection.
The more interesting question is why you want to provide the same service on two ports.

Connection reset error(server/client) -Using the class ObjectOutputStream

I'm trying to make a connection between a server and multiple clients, but it doesn't work even for one. All I want to do is to send from the client an object using the ObjectOutputStream class. The connection is made successfully at the beginning but when I try to send the object to the server it fails.
This is the client part which is written in the main method of a class:
Socket socket;
OutputStream out;
ObjectOutputStream fout;
boolean connected=false;
if (!connected) {
try {
socket = new Socket("localhost", 8000);
out = socket.getOutputStream();
fout = new ObjectOutputStream(out);
fout.flush();
connected = true;
fout.writeObject(ac1);//ac is an object of Plane class
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
This is the server:
public class server {
static class ServerThread implements Runnable {
Socket client = null;
public ServerThread(Socket c) {
this.client = c;
}
public void run() {
try {
System.out.println("Connected to client : "+client.getInetAddress().getHostName());
Plane ac=null;
InputStream in=client.getInputStream();
ObjectInputStream fin=new ObjectInputStream(in);
while(client.isConnected()){
ac = (Plane)fin.readObject();
System.out.println(ac.toString());
}
client.close();
} catch (Exception e) {
// System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String args[]) {
try {
ServerSocket server = new ServerSocket(8000);
while (true) {
Socket p = server.accept();
new Thread(new ServerThread(p)).start();
}
} catch (Exception ex) {
System.err.println("Error : " + ex.getMessage());
}
}
}
Could anyone tell me what is the problem?
Your client never closes the socket, and presumably exits, so the connection is reset. So close the socket.
NB isConnected() is not a valid loop condition. It will never become false. Your loop should terminate when EOFExceprion is caught.

How to pass object by socket in java Server Client

I'm new in Java Sockets, I have seen so many examples but I can't understand how to pass an argument from server to client and vice versa. My destination is to pass an Object that's why I'm using Object I/O Stream.
I have to classes Server and Player.
public class Server extends Thread{
public static final int TEST = 165;
ServerSocket serverSocket;
InetAddress address;
Player playerWhite;
public Server() {
start();
}
#Override
public void run() {
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendTestMessage(Player player) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(player.socket.getOutputStream());
testToClient.write(TEST);
testToClient.flush();
}
And the Player class:
public class Player extends Thread {
Socket socket;
Player() throws IOException
{
socket = new Socket(InetAddress.getLocalHost(), 6000);
}
#Override
public void run() {
try {
listenTestStream();
}
catch (IOException | ClassNotFoundException ex)
{
Logger.getLogger(CheckerPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void listenTestStream() throws IOException, ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
int message = ois.readInt();
//To test
System.out.println("Server listened: " + message);
}
I execute it as create a Server object in the other class.
When I have testing this application I saw that sometimes client is faster than Server. Is it possible to make him "wait" for server response?
Thanks for your response.
EDIT 1: PROBLEM SOLUTION:
From outside we should create:
Player player = new Player(); // (class player extends from Thread)
player.start();
and delete the Player variable - is not necessary, we need only Socket so:
Server:
Socket playerWhiteSocket
public void run() {
try
{
serverSocket = new ServerSocket(PORT);
playerWhiteSocket = serverSocket.accept();
sendMessage(playerWhiteSocket, "Hello");
}
catch(IOException | ClassNotFoundException ex)
{}
public void sendMessage(Socket socket, String message) throws IOException
{
ObjectOutputStream testToClient = new ObjectOutputStream(socket.getOutputStream());
testToClient.writeObject(message);
testToClient.flush();
}
In Player class we need get method:
public String receiveMessage() throws IOException, ClassNotFoundException
{
//socket is a variable get from Player class socket = new Socket("severHost", PORT);
ObjectInputStream messageFromServer = new ObjectInputStream(socket.getInputStream());
String message = (String) messageFromServer.readObject();
return message;
}
I would recomment doing this public void start(){
try {
ServerSocket = new ServerSocket(this.port,10,this.localAddress);
// set timeout if you want
//this.clientServerSocket.setSoTimeout(timeout);
// infinity loop
while(true)
{
//wait for a client connection
Socket socket = ServerSocket.accept();
// start thread for every new client
Thread t = new Thread(new AcceptClients(this.socket));
t.start();
System.out.println(L"new client connected");
// call garbage collector and hope for the best
System.gc();
}
} catch (IOException e) {
System.out.println("IO Error");
e.printStackTrace();
}
}
and then in another class
public class AcceptClients implements Runnable{
// socket
private Socket socket;
public AcceptClients (Socket socket){
this.socket = socket;
}
#Override
public void run() {
// what happens if a client connect
}
}
I always use this and it works fine
Suggested changes.
Create ServerSocket only once. If you have done it, you won't get "Address already in use" error
After creating Server Socket, you thread should be in while (true) loop to accept connection from client.
Once you create a client socket, pass that socket to thread.
Now Player is used to send communication from server to client socket. So You need one more class like PlayerClient which create a socket to Server IP and Port. Now PlayerClient should create one more thread to handle IO operations like you have done from server. In this case, creating a socket is not in while loop from client side. It create a socket to server once. Now you can run this PlayerClient program from multiple machines.
If you are just sending just primitive type, use DataOutputStream & DataInputStream instead of ObjectStreams
This code will become like this
try
{
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
System.out.println("server waits for players");
while ( true){
Socket socket = serverSocket.accept();
Player playerWhite = new Player(socket);
sendTestMessage(socket);// Move this method to Player thread and change the signature of this method accordingly to accept a socket
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
Player.java
Player(Socket socket) throws IOException
{
this.socket = socket;
start();
}
Have a look at this chat example for better understanding.
Yep it is.
It should work if you put it in a endlees loop like that:
try
{
while(true){
address = InetAddress.getLocalHost();
serverSocket = new ServerSocket(6000);
playerWhite = new Player();
System.out.println("server waits for players");
playerWhite.socket = serverSocket.accept();
playerWhite.start();
sendTestMessage(playerWhite);
}
}
catch (IOException ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
But I would not recommend to put this in a thread. Instead I would put the connection of a new client in a thread, so multiple clients can connect to the server

Multithreaded Server in Java - connection timeout exception while connecting from other computer

I have a problem with my application. If I run server and clients on the same computer it works fine. No errors. But if I run server on one PC and I try to connect form other computers I get "timeout exception" or If I manage to connect I will get errors while sending data.
Server code (not all):
// server loop - listening for connections
public void runServer()
{
try {
ServerSocket serverSocket = new ServerSocket(port, 10);
System.out.println("Server up.");
while (true)
{
System.out.println("waiting for new connection...");
Socket socket = serverSocket.accept();
System.out.println("Someone connected");
Thread t = new Thread (new ServerThread(socket));
t.start();
System.out.println("new thread");
}
} catch (IOException ex) {
Logger.getLogger(KsiegarniaServer.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Server error");
}
// this is thread that is opened when new client connects
private class ServerThread implements Runnable
{
Socket socket;
ObjectInputStream in;
ObjectOutputStream out;
String playerLogin;
int playerID;
public ServerThread(Socket s) {
this.socket = s;
}
public void run() {
try {
Msg m;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("Streams are ready!");
while ( (m = (Msg) in.readObject()).getHeader() != 0 )
{
respondToClient(m); // switch with cases that are running depending on message header
}
} catch (IOException ex) {
//Logger.getLogger(SpaceBattleGameServer.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("IOException - public void run()");
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException - public void run()");
} finally {
// other stuff
}

Java threads not starting / working as expected

I am implementing a simple client-server architecture where multiple clients should be able to connect to the server and strings could be exchanged between the server and client.
My idea is that I'll have two threads on each side: a listener, constantly checking if there is anything new in the inputstream, and a writer thread, that writes into the socket if there is something to write.
However, the second thread doesn't even start... Only the first sysout is displayed.
//start new thread to handle client input
new Thread(
new ServerWorker(clientSocket, this, this.getIdCounter())).start();
System.out.println("server side listener started");
//start new thread to handle client output
new Thread(new ServerWorkerListener(clientSocket)).start();
System.out.println("server side writer started");
Here is some code from the ServerWorker:
public void run() {
try {
OutputStream output = clientSocket.getOutputStream();
while (true) {
// output.write(("Pling!\n\n").getBytes());
for (Client tempClient : server.getClientList()) {
if ((tempClient.getId() == this.id)
&& tempClient.isShouldSend()) {
output.write((tempClient.getOutputStream() + "\n\n")
.getBytes());
tempClient.setInputStream("");
tempClient.setShouldSend(false);
}
}
}
} catch (IOException e) {
System.out.println("Error in serverWorker");
e.printStackTrace();
}
}
I really don't know what I'm missing...
Whole of ServerWorker:
public class ServerWorker implements Runnable {
protected Socket clientSocket = null;
protected String serverText = null;
protected int id;
protected Server server;
public ServerWorker(Socket clientSocket, Server server,
int id) {
this.clientSocket = clientSocket;
this.serverText = serverText;
this.id = id;
this.server = server;
}
public void run() {
try {
OutputStream output = clientSocket.getOutputStream();
while (true) {
// output.write(("Pling!\n\n").getBytes());
for (Client tempClient : server.getClientList()) {
if ((tempClient.getId() == this.id)
&& tempClient.isShouldSend()) {
output.write((tempClient.getOutputStream() + "\n\n")
.getBytes());
tempClient.setInputStream("");
tempClient.setShouldSend(false);
}
}
}
} catch (IOException e) {
System.out.println("Error in serverWorker");
e.printStackTrace();
}
}
}
Whole of ServerWorkerListener:
public class ServerWorkerListener implements Runnable {
private BufferedReader input;
private Socket clientSocket;
public ServerWorkerListener(Socket clientSocket) {
this.clientSocket = clientSocket;
run();
}
#Override
public void run() {
System.out.println("its running");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
while (true) {
System.out.println("it's looping");
String inputLine = null;
if ((inputLine = in.readLine()) != null) {
JOptionPane.showMessageDialog(null, inputLine, "InfoBox: "
+ "Message from client",
JOptionPane.INFORMATION_MESSAGE);
}
}
} catch (UnknownHostException e) {
System.err.println("Don't know about client");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to client");
System.exit(1);
}
}
}
You are invoking run() inside the constructor of ServerWorkerListener, which you must not do. The new thread ought to invoke run(), otherwise, since it contains an infinite loop, it will never return from the constructor and hence never invoke the Thread’s constructor, not to speak of its start method. So removing run() the invocation from the constructor should solve the problem.

Categories