ObjectInputStream throws EOFException on client-server setup - java

I am creating a client and server setup in order to send then server a command and then receive a reply. However when I run it the client throws and EOFException. I understand this is an end of file exception but I am not sure what I am doing wrong, or how I can fix it.
Code for Server:
public class Server {
private ServerSocket server;
private Socket connection;
private ObjectOutputStream output;
private ObjectInputStream input;
//SET UP AND RUN SERVER
public void startRunning() {
try {
server = new ServerSocket(6789, 100);
while (true) {
try {
waitForConnection();
setupStreams();
whileRunning();
} catch (Exception e) {
} finally {
closeAll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//DURING RUN
private void whileRunning() throws IOException {
String message = "You are now connected";
sendMessage(message);
System.out.println("Connected to client");
}
//WAIT FOR CONNECTION THEN DISPLAYS INFO
private void waitForConnection() throws IOException {
System.out.println("Waiting for connection.....");
connection = server.accept();
System.out.println("Now connected to " + connection.getInetAddress().getHostAddress());
}
//SETS UP STREAMS
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
//SEND MESSAGE TO CLIENT
private void sendMessage(String message) {
try {
output.writeObject("SERVER - " + message);
output.flush();
System.out.println("SERVER - " + message);
}
catch (Exception e) {
System.out.println("ERROR: Can't send message");
}
}
//CLOSE STREAMS AND SOCKETS
private void closeAll() {
System.out.println("Closing Connections");
try {
output.close();
input.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Code for starting the server:
public class RunServer {
public static void main(String[] args) {
Server server = new Server();
server.startRunning();
}
}
Code for client:
public class Client {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private String serverIP;
private Socket connection;
public Client(String host) {
serverIP = host;
}
public void startRunning() {
try {
connectToServer();
setupStreams();
whileRunning();
}
catch (Exception e) {
} finally {
closeAll();
}
}
// CONNECT TO SERVER
public void connectToServer() throws IOException {
System.out.println("Attempted connection...");
connection = new Socket(InetAddress.getByName(serverIP), 6789);
System.out.println("Connected to: " + connection.getInetAddress().getHostName());
}
// SET UP STREAMS
private void setupStreams() throws IOException { output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
System.out.println("\nStreams Connected");
}
// WHILE CHATTING
private void whileRunning() throws IOException {
do {
try {
message = (String) input.readObject();
System.out.println(message);
} catch (Exception e) {
e.printStackTrace(); //In to view exception
System.out.println("Unable to get message");
System.exit(0); //In to stop it looping forever (Known issue)
}
} while (!message.equals("SERVER - END"));
}
// CLOSE STREAMS AND SOCKETS
public void closeAll() {
System.out.println("Closing sockets, closing streams");
try {
output.close();
input.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Code for starting the client:
public class RunClient {
public static void main(String[] args) {
Client client = new Client("localhost");
client.startRunning();
}
}
When I run the client it constantly loops saying "Unable to get message" forever.
However when I view the exception and exit the code (as added in) I get this problem:
Attempted connection...
Connected to: localhost
Streams Connected
SERVER - You are now connected
java.io.EOFException
Unable to get message
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at main.Client.whileRunning(Client.java:53)
at main.Client.startRunning(Client.java:26)
at main.RunClient.main(RunClient.java:7)
Any help or suggestions would be much appreciated. Thanks :)

EOFException is thrown when you get to the end of the stream, which happens when the peer closes the connection.
You need to catch it separately and not treat it as an error.
I also suggest you change System.exit(0); to break;.

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

java.net.SocketException: Connection reset occurs from server socket

public class NewClass {
ServerSocket myServerSocket;
boolean ServerOn = true;
public NewClass() {
try {
myServerSocket = new ServerSocket(8888);
} catch (IOException ioe) {
System.out.println("Could not create server socket on port 8888. Quitting.");
System.exit(-1);
}
while (ServerOn) {
try {
Socket clientSocket = myServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException ioe) {
System.out.println("Exception found on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
try {
myServerSocket.close();
System.out.println("Server Stopped");
} catch (Exception ioe) {
System.out.println("Error Found stopping server socket");
System.exit(-1);
}
}
public static void main(String[] args) {
new NewClass();
}
class ClientServiceThread extends Thread {
Socket myClientSocket;
boolean m_bRunThread = true;
public ClientServiceThread() {
super();
}
ClientServiceThread(Socket s) {
myClientSocket = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
System.out.println(
"Accepted Client Address - " + myClientSocket.getInetAddress().getHostName());
try {
in = new BufferedReader(new InputStreamReader(myClientSocket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(myClientSocket.getOutputStream()));
while (m_bRunThread) {
String clientCommand = in.readLine();
if (clientCommand != null) {
System.out.println("Client Says :" + clientCommand);
}
if (!ServerOn) {
System.out.print("Server has already stopped");
out.println("Server has already stopped");
out.flush();
m_bRunThread = false;
}
if (clientCommand.equalsIgnoreCase("quit")) {
m_bRunThread = false;
System.out.print("Stopping client thread for client : ");
} else if (clientCommand.equalsIgnoreCase("end")) {
m_bRunThread = false;
System.out.print("Stopping client thread for client : ");
ServerOn = false;
} else {
out.println("Server Says : " + clientCommand);
out.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
myClientSocket.close();
System.out.println("...Stopped");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Client Code
public class Client {
public static void main(String[] args) throws IOException {
Socket s = new Socket(InetAddress.getLocalHost(), 8888);
PrintWriter out =new PrintWriter(s.getOutputStream(), true);
out.print("KKKKKKKKKKKKK \r\n");
out.flush();
out.close();
}
The purpose of the above code is to create server socket and client socket to pass data between server and client.When the client sends the data to server .server grab the message and print it on the screen but with following exception.The pop up from the String clientCommand = in.readLine(); line which appeared on server code.
java.net.SocketException: Connection reset
Your code is invalid. Your server code relies on the client implementing the protocol correctly, which this client doesn't. Bad habit. Defensive coding is required. If clientCommand == null you must exit this read loop and close the socket. Your present code will attempt to write to the closed connection, which produces exactly this exception ... later.

Set server listening a sending messages from (servers/client) to (server/client) separately for each client

Trying to write - distributive simulation framework, where program is represented by an array with moving objects, server send command to move, client answer objects out of array
Goal - server send text message to each connected client separately
- client answer
Problem - can not find a way how to implement server listening and writing to one choosed client
Is there anyone, please, who can help me or get some idea?
private ServerSocket serverSocket;
private ArrayList<BufferedReader> clientBufReaders;
private ArrayList<BufferedWriter> clientBufWriters;
public static void main(String[] args) {
Server server = new Server();
}
public Server() {
try {
this.serverSocket = new ServerSocket(23456);
this.clientBufReaders = new ArrayList<BufferedReader>();
this.clientBufWriters = new ArrayList<BufferedWriter>();
this.clients();
} catch (IOException e) {
e.printStackTrace();
}
}
private void clients() {
Thread acceptThread = new Thread(new Runnable() {
private Scanner in;
public void run() {
while (true) {
try {
Socket clientSocket = serverSocket.accept();
clientBufReaders.add(new BufferedReader(new InputStreamReader(clientSocket.getInputStream())));
clientBufWriters.add(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())));
this.in = new Scanner(System.in);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
);
acceptThread.start();
while (true) {
synchronized (clientBufReaders) {
for (BufferedReader in : clientBufReaders) {
try {
if (in.ready()) {
System.out.println(in.readLine());
} else {
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

Handling multi Java TCP clients with Threads

I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work

Server is only reading the first object that is sent from the client

I'm having issues sending objects to a server. Right now, I have a server setup and listening for clients. The client connects, sends a test object (just a String) and outputs it to the command line. It works for the first string sent but none after that.
Server (Hivemind.java):
// Open server socket for listening
ServerSocket ss = null;
boolean listening = true;
try {
ss = new ServerSocket(PORT_NUMBER);
} catch (IOException e) {
System.err.println("Cannot start listening on port " + PORT_NUMBER);
e.printStackTrace();
}
// While listening is true, listen for new clients
while (listening) {
Socket socket = ss.accept();
ServerDispatcher dispatcher = new ServerDispatcher(socket);
dispatcher.start();
}
// Close the socket after we are done listening
ss.close();
Server Thread (ServerDispatcher):
public ServerDispatcher(Socket socket) {
super("ServerDispatcher");
this.socket = socket;
}
public void run() {
System.out.println("Client connected");
try {
input = socket.getInputStream();
objInput = new ObjectInputStream(input);
Object obj = null;
try {
obj = (String)objInput.readObject();
} catch (ClassNotFoundException ex) {
Logger.getLogger(ServerDispatcher.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(obj);
} catch (IOException ex) {
Logger.getLogger(ServerDispatcher.class.getName()).log(Level.SEVERE, null, ex);
}
Connection Class (HivemindConnect.java):
public HivemindConnect(int port) {
this.port = port;
url = "localhost";
}
public HivemindConnect(int port, String url) {
this.port = port;
this.url = url;
}
public void connect() {
try {
socket = new Socket(url, port);
output = socket.getOutputStream();
objOutput = new ObjectOutputStream(output);
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
try {
objOutput.close();
output.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void send(Object obj) {
try {
objOutput.writeObject(obj);
objOutput.flush();
} catch (IOException ex) {
Logger.getLogger(HivemindConnect.class.getName()).log(Level.SEVERE, null, ex);
}
}
CustomerTopComponent:
// When the TC is opened connect to the server
#Override
public void componentOpened() {
hivemind = new HivemindConnect(9001);
hivemind.connect();
}
private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {
hivemind.send(txtText.getText());
}
// When the TC is closed close the connection to the server
#Override
public void componentClosed() {
hivemind.close();
}
You need a loop like this:
while(objInput.available()>0){
Object obj = null;
obj = (String)objInput.readObject();
System.out.println(obj);}
Or something similar.

Categories