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

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
}

Related

Why is there a "SocketException: Connection reset" when not closing client's output stream?

In a simple Server Client communication I always get the "java.net.SocketException: Connection reset" on the serverside, if the client does not close the outputstream of it's socket directly after sending out the data via BufferedWriter.
If I close the client's outputstream everything works fine.
But obviously the client wants eventually to send more than one String (then the server needs to handle the connection in a new Thread). But I don't even get that far, because ofe the problem above...
Thanks for helping!!
Here is some condensed code to show the problem.
This is the server class:
public class TestServerCharacterStream {
public static void main(String[] args) {
System.out.println("### Started");
TestServerCharacterStream testServerCharacterStream = new TestServerCharacterStream(9498);
testServerCharacterStream.waitForData();
System.out.println("### Terminated");
}
private int port;
private ServerSocket serverSocket;
private BufferedReader in;
public TestServerCharacterStream(int port) {
this.port = port;
try {
this.serverSocket = new ServerSocket(port);
System.out.println("[SERVER] : Server started!");
} catch (IOException e) {
System.err.println("Cannot open new server socket!");
e.printStackTrace();
}
}
public void waitForData() {
Socket clientSocket = null;
try {
System.out.println("[SERVER] : Wait for data on port " + port + " ...");
clientSocket = serverSocket.accept();
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String incoming = in.readLine();
System.out.println("[SERVER] : Incoming message: " + incoming);
} catch (IOException e) {
System.err.println("Error while accepting connection or reading input!");
closeStreamAndSocket(clientSocket, in);
closeServerSocket();
e.printStackTrace();
}
}
private void closeStreamAndSocket(Socket socket, BufferedReader in) {
try {
if (in != null) {
in.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
System.err.println("Cannot close stream or socket.");
e.printStackTrace();
}
}
private void closeServerSocket() {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
System.err.println("Cannot close serverSocket.");
e.printStackTrace();
}
}
}
This is the Client Class:
As mentioned, it works if closing the outputstream (see the comment). To use flush() or not does not make any difference. The only way to solve it is out.close();
But I want to use the BufferedWriter again, withot connect always again to the server.
public class TestClientCharacterStream {
public static void main(String[] args) {
System.out.println("### Started");
TestClientCharacterStream testClientCharacterStream = new TestClientCharacterStream("localhost", 9498);
testClientCharacterStream.sendData("Hello!!!");
System.out.println("### Terminated");
}
private InetSocketAddress adress;
private Socket clientSocket;
private BufferedWriter out;
public TestClientCharacterStream(String serverIp, int port) {
this.adress = new InetSocketAddress(serverIp, port);
try {
clientSocket = new Socket();
clientSocket.connect(adress, 10000);
this.out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
} catch (IOException e) {
System.err.println("Something went wrong on instantiating a new TestClientCharacterStream");
e.printStackTrace();
}
}
public void sendData(String string) {
try {
out.write(string);
System.out.println("[CLIENT] : Sent new message: " + string);
out.flush();
out.close(); // If I don't close the stream, I'm going to get a "java.net.SocketException: Connection reset" on the server
} catch (IOException e) {
closeStreamAndSocket(clientSocket, out);
e.printStackTrace();
}
}
private void closeStreamAndSocket(Socket socket, BufferedWriter out) {
try {
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
System.err.println("Cannot close stream or socket.");
e.printStackTrace();
}
}
}
The servers Output:
### Started
[SERVER] : Server started!
[SERVER] : Wait for data on port 9498 ...
Error while accepting connection or reading input!
java.net.SocketException: Connection reset
at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:323)
at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350)
at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803)
at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:270)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:313)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:188)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:177)
at java.base/java.io.BufferedReader.fill(BufferedReader.java:162)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:329)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:396)
at TestServerCharacterStream.waitForData(TestServerCharacterStream.java:40)
at TestServerCharacterStream.main(TestServerCharacterStream.java:12)
### Terminated

open a secure socket on the server side

I have a server application that opens a socket and then listens to any connections being made on that socket.
public Server(){
try {
ServerSocket sSocket = new ServerSocket(nPort);
System.out.println("Server started at: " + new Date());
System.out.println("===============================================\n");
//Loop that runs server functions
while(true) {
//Wait for a client to connect
Socket socket = sSocket.accept();
socket.setSoTimeout(30000);
//Create a new custom thread to handle the connection
ClientThread cT = new ClientThread(socket, nPort);
//Start the thread!
new Thread(cT).start();
}
}
catch(IOException ex) {ex.printStackTrace();}
}
Whenever new connection attempted, a new thread is started using the ClientThread class. The ClientThread class has a run method that does all the things need to be done (read input, send respons etc.)
public class ClientThread implements Runnable{
private Socket threadSocket;
private int nPort = 0, maxCon = 2;
//This constructor will be passed the socket
public ClientThread_v3(Socket socket, int port){
threadSocket = socket;
nPort = port;
}
public void run(){
System.out.println("New connection at " + new Date() + "\n");
try {
DataInputStream in = new DataInputStream (threadSocket.getInputStream());
out = new DataOutputStream (threadSocket.getOutputStream());
while (running){
// do some stuff ....
// go to sleep
Thread.sleep(1000);
}
}
catch (IOException ex) {ex.printStackTrace();}
catch (InterruptedException ex) {ex.printStackTrace();}
finally {
try {
threadSocket.close();
System.out.println("Connection closed.\n");
} catch (IOException ex) {ex.printStackTrace();}
}
}}
My question is how do i make the socket connection secure? how do i open a secure connection?
I don't want to use any HTTP packages for that matter, want to keep it as a socket connection.
Any help would be appreciated. Thank you.

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.

client/server connection closing causes loop error

I got to stage where client and server communicate, sending messages from and to each other.
The problem I am having is how to close the connection without causing an error?
If I terminate one of the apps (either server or client) that causes the connection to be lost, and then it causes the loop that is waiting for input to loop indefinitely and showing null's.
I tried closing sockets, buffers and even the thread, didn't work.
This is the client side
public void onClick(View view) {
try {
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
This is the server side
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVERPORT);
} catch (IOException e) {
e.printStackTrace();
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(
socket);
new Thread(commThread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Both use these classes:
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(
this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
updateConversationHandler.post(new updateUIThread(read));
//***HERE EXTRA BIT FOR THE SERVER
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class updateUIThread implements Runnable {
private String msg;
public updateUIThread(String str) {
this.msg = str;
}
#Override
public void run() {
text.setText(msg);
}
}
the only difference is the server has this bit where it says above ***HERE EXTRA BIT FOR THE SERVER
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
out.println("Message recieved");
so basically, client connects, server accepts, then client sends message, servers receives message and shows it, and then sends "Message received" to the client, and the client shows it.
All this works fine, but once the connection is lost, they hang on showing null repeatedly, and I have to force the app to close.
You aren't checking for end of stream. If readLine() returns null, the peer has closed the connection, and you must do likewise and stop reading.
It's hard to believe you really need a new thread for every line to update the UI.

Multithread Server 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.

Categories