Server can't read object from client socket stream, why? - java

I have a server that wait in a loop for clients to connect. Once a client connect a new thread is created to handle that client requests. The server and the client connect with each other easily, but the problem I have with that thread is that it doesn't seem to read the object that the client send to the pipe. I've checked everywhere but can't seem to find the problem.
The server code:
public class Server
{
private ServerSocket server;
public Server(int port) throws IOException
{
//Port 9367
this.server = new ServerSocket(port);
this.server.setReuseAddress(true);
}
public void start() throws IOException
{
System.out.println("Waiting for client...");
while(true)
{
new Thread(new ClientRequestManager(server.accept())).start();
System.out.println("client found !");
}
}
}
ClientRequestManager code:
public void run()
{
try {
ObjectInputStream objectInput = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("Waiting for request...");
while(true)
{
DataRequest request = (DataRequest)objectInput.readObject();
if(request instanceof TestDataRequest)
{
new Thread(new TestEntityManager((TestDataRequest)request, this.clientSocket)).start();
System.out.println("Client dispatched to the test entity manager !");
}
System.out.println("Can't find the right entity manager !");
}
} catch (Exception e) { }
}
The server seem to get stuck here: DataRequest request = (DataRequest)objectInput.readObject();
Here's the basic code I've written for the client to test the server:
//TestDataRequest inherit DataRequest
TestDataRequest request = new TestDataRequest();
request.setID(30);
request.setDescription("test");
Socket serverSocket = new Socket("localhost",9367);
ObjectOutputStream clientOutputStream = new ObjectOutputStream(serverSocket.getOutputStream());
System.out.println("Sending data...");
clientOutputStream.writeObject(request);
clientOutputStream.flush();
System.out.println("Data send !");
I don't get any error, the thread just block. I suppose it's waiting for object to be written to the pipe, like it should be, but it's still blocking when a client write an object to the pipe. I don't understand why. The object implements serializable... The server and the client seem to be connected to each other and writing/reading to the same pipe...
The server: addr=/127.0.0.1,port=49654,localport=9367
The client: addr=localhost/127.0.0.1,port=9367,localport=49654
Can somebody please explain to me what I'm doing wrong ?

Related

java.io.EOFException when reading from socket

I have a server and a client set up in this way. I can't find the cause of the EOFException, because it happens randomly. It throws the following exception every time a client connects, but I can't figure out the source of it. It always occurs before it reads what the client has sent. The exception always is at this line:
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Here is the exception:
java.io.EOFException
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2860)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3355)
at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:939)
at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:381)
at com.denesgarda.Socketeer.data.End$3.run(End.java:62)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End$3.run(End.java:76)
at com.denesgarda.Socketeer.data.End.listen(End.java:83)
at Server.<init>(Server.java:10)
at SStart.main(SStart.java:5)
Here is my server code:
if(listener == null) this.voidListener();
ServerSocket serverSocket = new ServerSocket(port);
End THIS = this;
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
try {
Socket socket = serverSocket.accept();
socket.setSoTimeout(10000);
Connection connection = new Connection(THIS, new End((((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress()).toString().replace("/","")), port, listener);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
if (o.equals("01101100 01101001 01110011 01110100 01100101 01101110 00100000 01110011 01110100 01100001 01110010 01110100")) {
listener.event(new ConnectionEvent(connection));
listener.event(new ConnectionSuccessfulEvent(connection));
}
else {
listener.event(new ReceivedEvent(connection, o));
}
socket.close();
}
catch(EOFException e) {
e.printStackTrace();
}
this.run();
}
catch(Exception e) {
e.printStackTrace();
}
}
};
timerTask.run();
Here is my client code:
if(listener == null) this.voidListener();
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
socket.close();
}
What I've Tried
I've tried to fix this issue many times before. I tried to create object output streams. I've switched the order that I initialize the object input stream and object output stream. This is so that the server doesn't get frozen in a deadlock with the client. I have no idea what could be causing this error.
I think I know what is going on here, but I can't be certain because your code is fragmentary, and the symptoms are not well characterized. (The exceptions are unlikely to really be random, for example.)
First there is one indisputable fact. A one side of a connection sees an EOFException because the other side has closed the network connection. That's what that exception means.
In your case, the server gets the exception in the ObjectInputStream constructor because the constructor attempts to read an object stream header that the client side never sends ... on that connection.
Now, the theory. I think I know why. Here is the relevant part of your code (with some bits snipped out for brevity).
Socket socket = new Socket(address, port);
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
[...]
socket.close();
[...]
}
});
send("Message");
public void send(Object object) throws IOException {
Socket socket = new Socket(THAT.getAddress(), this.port);
[...]
}
Notice that there are two sockets! The first one is created and passed to the shutdown hook. The second one is created and used within send and then closed.
I think the problem is the first Socket. When that is created, it establishes a connection to the server. The server code will accept it and then attempt to read. The read will block ... since the client side hasn't written anything to that socket. The client will then call send which opens and uses a different Socket.
Eventually, the client application exits.
When it exits, the shutdown hook closes the first socket. That causes the server side to see the end of stream ... and triggers the EOFException.
So how to fix this?
It rather depends on the "big picture". Is the real client sending a single message to the server, or does it need to reuse the socket to send multiple messages?
Assuming the former, the solution is simple:
Get rid of the code that creates a socket and passes it to a shutdown hook. As you have written it, it serves no useful purpose.
Rewrite the send method to use try with resources; e.g.
public void send(Object object) throws IOException {
try (Socket socket = new Socket(THAT.getAddress(), this.port);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(object);
}
}
Note that the above will automatically close the 3 resources in the correct order.

problem with connecting multiple clients to a server

hey I'm writing a simple code with a server socket and multiple clients which the server gets every client's username and stores them in a hashmap.the server accepts a socket client and the client enters the username but again the server accept the same socket client and it wants its username and the code stops here.i want it to work for multiple clients not just one.
server class:
public class Server implements Serializable{
// [..]
public void serverConnect() throws IOException, ClassNotFoundException
{
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true)
{
System.out.println("Waiting ...");
socket=listener.accept();
for (Socket socket:socketList.keySet())
{
if (this.socket==socket)
{
checkSocket=false;
}
}
if (checkSocket)
{
socketList.put(socket,socketNumber);
System.out.println("Client is connected");
inputReader = new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(inputReader);
user = reader.readLine();
Server.userList.add(user);
socketNumber++;
}
checkSocket=true;
}
}
}
client class:
public class Client {
public Client() {
}
public void clientConnect() throws UnknownHostException, IOException {
System.out.println("enter your username");
Scanner scanner = new Scanner(System.in);
String msg = scanner.nextLine();
Socket socket = new Socket("localhost", 9090);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println(msg);
}
}
In principle you have the workings of single thread server (which means it can accept only one client connection at a time). The main issue is that you have over-complicated how you receive a connection.
You can simplify your current code by dealing by moving the client connection socket and readers into the local scope and dealing with the socket directly.
public void serverConnect() throws IOException {
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} catch (IOException ignore) {
} finally {
socket.close();
}
}
}
As you can see you don't need to keep hold of the socket beyond reading the value sent. If you are only expecting the one line of data from the client, you should also close the socket otherwise the client can hold the server hostage by not sending any data until the socket timeout is reached.
Further to this you also want to wrap the code inside the while loop with a try/catch block to prevent an exception terminating the server.
As I mentioned in the opening paragraph this code works as a single threaded server and it can only respond to a single request at a time. If you want to accept and process multiple requests you will need to spawn a new thread to handle the response. I would recommend constructing your code as below but for the sake of brevity you could do something like below:
public void serverConnect() throws IOException {
int MAX_WORKERS = 100;
ExecutorService service = Executors.newFixedThreadPool(MAX_WORKERS);
ServerSocket listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
service.submit(() -> {
System.out.println("Client is connected");
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} finally {
socket.close();
}
} catch (Throwable ignore) {
}
});
}
}
So all that is happening above is that we are creating a thread pool of 100 threads using the ExecutorService. This means in theory we can accept 100 concurrent connections.
When a connection is accepted, we submit the socket and worker code to a thread which means that the main thread can return to listening for a new connections.

Writing Java Server to handle multiple client concurrently (simultaneously)

I am working on a program where I have a Server and Client class, but at the moment it only handles only one client at a time.
I need the server to be able to handle multiple clients concurrently (simultaneously), using multithreading.
Here is my Server code; how can I change it to handle multiple clients concurrently?
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(8945);
Server serverInstance = new Server();
System.out.println("Server is running. Waiting for client.");
while(true) {
server.socket = s.accept();
System.out.println("Client connected");
serverInstance.run();
System.out.println("Client disconnected. Waiting for new client.");
}
}
public void run() {
try {
try {
in = new Scanner(socket.getInputStream());
out = new PrintWriter(socket.getOutputStream());
RequestHandlingMethod();
} finally {
socket.close();
}
} catch (IOException e) {
System.err.println(e);
}
}
Create a separate class that handles the client. Make it implement Runnable so that you can just start a separate Thread with it.
public class ClientHandler implements Runnable {
private final Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try (Socket socket = this.socket;
Scanner in = new Scanner(socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream()) {
//todo: do whatever you need to do
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println("Client disconnected.");
}
}
Then in your server you do:
System.out.println("Waiting for new client connection");
Socket clientSocket = s.accept();
System.out.println("Client connected");
new Thread(new ClientHandler(clientSocket)).start();
If you don't want to create a lot of disposable Threads, you might want to consider using an ExecutorService with a cached thread pool (or another thread pool of your choice if you prefer).
You would just create a new ExecutorService with ExecutorService executor = ExecutorService.newCachedThreadPool() and then inside your loop you do:
System.out.println("Waiting for new client connection");
Socket clientSocket = s.accept();
System.out.println("Client connected");
executor.submit(new ClientHandler(clientSocket));
If you think you are going to have a lot of concurrent clients, you might want to look at using a non-blocking server with NIO instead. It will have 1 single event loop thread instead (doesn't block on the accept) and handles all I/O events in there, and you can have a pool of worker threads that do the client handling logic.

Threads & networking issue

Given the following code:
Client c1 = new Client();
c1.connect("127.0.0.1",1300);
Connect function:
public void connect(String serverName, int port)
{
try {
Socket socket = new Socket(serverName,port);
connection = new ConnectionProxy(socket);
connection.start();
}
catch(IOException e)
{
e.printStackTrace();
}
}
(ConnectionProxy class extends Thread) :
public class ConnectionProxy extends Thread {
private Socket socket;
private InputStream is;
private OutputStream os;
private StringConsumer client;
public ConnectionProxy(Socket socket)
{
this.socket = socket;
try {
is = socket.getInputStream();
os = socket.getOutputStream();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void run () {
DataInputStream dis = new DataInputStream(is);
DataOutputStream dos = new DataOutputStream(os);
while (socket != null)
{
try {
String msg = dis.readUTF();
System.out.println(msg);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
I'm trying to implement a chat and I'm finding it difficult to send a message written by a client to all of the currently connected clients.
How could I do that? Should I hold the reference for each object (like c1) on the server side, or should I hold that ConnectionProxy thread on the server side?
If not, how do I implement that correctly and efficiently?
Would love to get some help!
Thanks!
Without being given much code, I'll outline what you'd want to do to achieve your goal.
On your server:
Keep an array or something similar of all connected client objects
Implement a send() function in your client class
Implement a broadcast() function that loops through the client list and sends each of them the message (using the aforementioned send() function
Make sure to keep track of (and remove) any dead/disconnected clients from your list, otherwise you'll run into trouble trying to send to them.
On your client:
Make sure you send a "connection terminated" message when you close/disconnect to tell the server you're leaving (makes it easier for the server to remove you)
The server should create a new client handler thread for each incoming connection.
For example, on the server side try something like:
ServerSocket server = new ServerSocket(port);
while (true) {
Socket client = server.accept();
//add incoming client to connected clients vector.
HandleClient c = new HandleClient(client);
clients.add(c);
}
After creating and storing clients in your vector of clients, you can the implement on the HandleClient class run() method a bufferReader (again not a must) to get your client text

how to communicate between client and server in java

I have a chat program. Now the code works for communicate between client and server via command line. But it gives an exception (java.net.SocketException: Socket is closed) while running. Please help me to fix that problem.
In a java chat program,how will the communication be implemented between client and server?
ie.
client<-->server (between server and client)
or
client A<-->server<-->client B (server act as a bridge between two clients)
Is the 2 way communication can be implemented through a single socket?
Are there any other methods ?
How to communicate more than one client simultaneously?
server code
class Server
{
ServerSocket server;
Socket client;
public Server()
{
try
{
server = new ServerSocket(2000);
System.out.println("\tServer Started..........");
while (true)
{
client = server.accept();
Send objsend = new Send(client);
Recive objrecive = new Recive(client);
//client.close();
}
}
catch (Exception e)
{
System.out.println("Exception4 " + e);
}
}
public static void main(String arg[])
{
new Server();
}
}
class Recive implements Runnable
{
Socket client;
public Recive(Socket client1)
{
client=client1;
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
ObjectInputStream ois;
Message M=new Message();
try
{
ois = new ObjectInputStream(client.getInputStream());
M = (Message)ois.readObject();
M.display();
ois.close();
}
catch (Exception e)
{
System.out.println("Exception1 " + e);
}
}
}
class Send implements Runnable
{
Socket client;
public Send(Socket client1)
{
client=client1;
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
try
{
System.out.println("Me(server)");
M.strmessage=br.readLine();
ObjectOutputStream oos=new ObjectOutputStream(cli ent.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
catch (Exception e)
{
System.out.println("Exception " + e);
}
}
}
client code
class Client
{
public static void main(String arg[])
{
try
{
Send objsend=new Send();
Recive objrecive=new Recive();
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Send implements Runnable
{
public Send()
{
Thread trsend=new Thread(this);
trsend.start();
}
public void run()
{
try
{
Message M=new Message();
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
while(true)
{
System.out.println("Me(client)");
M.strmessage=br.readLine();
Socket client=new Socket("localhost",2000);
ObjectOutputStream oos=new ObjectOutputStream(client.getOutputStream());
oos.writeObject((Message)M);
oos.flush();
oos.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
class Recive implements Runnable
{
public Recive()
{
Thread trrecive=new Thread(this);
trrecive.start();
}
public void run()
{
try
{
while(true)
{
Socket client=new Socket("localhost",2000);
ObjectInputStream ois=new ObjectInputStream(client.getInputStream());
Message CNE=(Message)ois.readObject();
CNE.display();
ois.close();
}
}
catch(Exception e)
{
System.out.println("Exception "+e);
}
}
}
First of all, don't close the streams in every run().
Secondly, check whether port for server which you are using is free.
This program makes your pc both host and server.
import java.io.IOException;
import java.net.*;
public class ClientServer {
static byte[] buffer = new byte[100];
private static void runClient() throws IOException {
byte buffer[] = new byte[100];
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds=new DatagramSocket();
int pos = 0;
while (pos<buffer.length) {
int c = System.in.read();
buffer[pos++]=(byte)c;
if ((char)c =='\n')
break;
}
System.out.println("Sending " + pos + " bytes");
ds.send(new DatagramPacket(buffer, pos, address, 3000));
}
private static void runServer() throws IOException {
InetAddress address = InetAddress.getLocalHost();
DatagramSocket ds = new DatagramSocket(3000, address);
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);
String s=new String(dp.getData(),0,dp.getLength());
System.out.print(s);
}
public static void main(String args[]) throws IOException {
if (args.length == 1) {
runClient();
} else {
runServer();
}
}
}
also follow this link
There could be multiple places where the exception could be thrown. Without a stack trace it is difficult to state so accurately, as to the cause of failure.
But the root cause, is essentially due to the fact that you are closing the InputStream of the socket in your Receiver threads after reading a message, and closing the OutputStream of the socket in your Sender threads after sending a message. Closing either of these streams will automatically close the socket, so you if attempt to perform any further operation on it, a SocketException will be thrown.
If you need to ensure that your server and client do not shutdown in such an abrupt manner, you'll have to keep reading the InputStream (until you get a special message to shutdown, for instance). At the same time, you'll also have to keep writing to the OutputStream. Two-way communication is definitely possible, and the posted code is capable of the same (if the socket remains open).
If you have to handle multiple clients, you'll need multiple reader and writer threads on the server, each listening on an instance of a Socket returned from ServerSocket.accept(); in simpler words, you need a reader-writer pair listening on a distinct socket on the server for each client. At the moment, multiple clients can connect to the Server, as each incoming connection is provided its own client Socket object on the Server, that is provided to individual reader and writer threads. The main Server thread can continue to receive incoming connections and delegate the actual work to the reader-writer pairs.
chat programms normaly have a server through which all communication goes. The reason is that other wise every client needs to know how to reach every other client. And that doesn't work in the general case.
So you'll have a server, every client registers and talks with the server, which will forward messages to other clients.
Mostly communication is done via HTTP cause this is likely to go through firewalls and proxies. You probably want to read up on long polling if you are planning for anything serious.

Categories