1

I'm trying to get my head around the ObjectInputStream/ObjectOutputStream, so I create a very simple server-client application where the client sends a HashMap object over the created stream and the server receives that and prints it out.

This my server code:

import java.io.*;
import java.net.*;

public class Server {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ServerSocket server = new ServerSocket(4444);
        while (true) {
            Socket socket = server.accept();
            ObjectInputStream objIn = new ObjectInputStream(socket.getInputStream());

            if (objIn.readObject() != null) {
                System.out.println(objIn.readObject());
            }
        }    
    }
}

This my client code:

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;

public class Client {

    public static void main(String[] args) throws IOException {
        Socket sock;
        int port = 4444;
        HashMap<Integer, String>  mapSend= new HashMap<>();
        mapSend.put(1,"row1");
        mapSend.put(2,"row2");

        sock = new Socket(InetAddress.getLocalHost(), port);
        ObjectOutputStream objOut = new ObjectOutputStream(sock.getOutputStream());

        objOut.writeObject(mapSend);
        objOut.flush();
    }
}

I run the server file and it runs ok.
Then I run the client file and I get the following error on the server:

    Exception in thread "main" java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:189)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2308)
    at java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2716)
    at java.io.ObjectInputStream$BlockDataInputStream.readFully(ObjectInputStream.java:2740)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1978)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:499)
    at java.util.HashMap.readObject(HashMap.java:1115)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at iotest.Server.main(Server.java:17)
Java Result: 1

P.S. I don't know if I have to do something to serialize the HashMap, but I think I saw somewhere that this is handled internally by Java. I might tough be wrong.

EDIT after Aaron answer I implemented this part in my server as Aaron suggested:

Object objRead=objIn.readObject();
            if (objRead != null) {
                System.out.println(objRead);
            }

and now I get this error,again from server,after I run the client:

Exception in thread "main" java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:189)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2308)
    at java.io.ObjectInputStream$BlockDataInputStream.read(ObjectInputStream.java:2716)
    at java.io.ObjectInputStream$BlockDataInputStream.readFully(ObjectInputStream.java:2740)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1978)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at java.util.HashMap.readObject(HashMap.java:1154)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at iotest.Server.main(Server.java:17)
Java Result: 1

2 Answers 2

1

You're reading the object twice, but only printing the second time. So the client is probably shutdown by the time you try to read the second time, and so the socket has been closed on the remote end, hence exception.

You're reading in an object on the != null check. You don't print it. Then you try to read it again and it bombs.

Once you read from the stream, it's been read. It's a stream, not a buffer. You might want to buffer the read, and then you can inspect that buffer as much as you like.

Simplest example...

Object o = outputStream.readObject();
if(o != null) {
 system.out.println(o);
}
Sign up to request clarification or add additional context in comments.

9 Comments

Yes. The key is to remember that the stream isn't buffered. Once you've read it, it's gone.
I accidentally deleted my comment. Thank you very much for the clarification.
@akafortes Like when you turn on the beer tap - you can turn on the beer to see if there's any beer left, but unless you catch the spilled beer in a glass, you can't then say "great, there's beer available" and then try to drink the beer you've already spilled while testing if any is available.
is the "outputStream" supposed to be like that or is it a typo and you meant to write "inputStream"?
@akafortes yes, sorry. InputStream.
|
1

This happen because the client socket is automatically terminated after that all its code is executed.

For example, if you add

while (true) {
    System.out.println("no operation");
    try {
        Thread.sleep(10000);
    } catch(InterruptedException e) {
        e.printStackTrace();
    }
}

at the end of your client code, you don't get any Connection Reset, because your client socket will never be terminated.

So, the client side socket is closed and the server side socket has to handle this exception. You should just go out from the loop when you get this exception, so:

boolean connected = true;
while (connected) {
    try {
        //your code
    } catch (SocketException e) {
        connected = false;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.