1

我试图了解ObjectInputStream/ObjectOutputStream,所以我创建了一个非常简单的服务器-客户端应用程序,客户端通过创建的流发送 HashMap 对象,服务器接收并打印出来。

这是我的服务器代码:

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());
            }
        }    
    }
}

这是我的客户代码:

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();
    }
}

我运行服务器文件,它运行正常。
然后我运行客户端文件,我在服务器上收到以下错误:

    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

PS我不知道我是否必须做一些事情来序列化HashMap,但我想我在某处看到这是由Java内部处理的。我可能是错的。

亚伦回答后编辑 我按照亚伦的建议在我的服务器中实现了这部分:

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

现在我在运行客户端后再次从服务器收到此错误:

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
4

2 回答 2

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;
    }
}
于 2015-04-19T19:47:48.977 回答
1

您正在读取该对象两次,但仅打印第二次。因此,当您第二次尝试读取时,客户端可能已关闭,因此套接字已在远程端关闭,因此异常。

您正在 != null 检查中读取对象。你不打印它。然后你尝试再次阅读它,它会爆炸。

从流中读取后,它已被读取。它是一个流,而不是一个缓冲区。您可能想要缓冲读取,然后您可以根据需要检查该缓冲区。

最简单的例子...

Object o = outputStream.readObject();
if(o != null) {
 system.out.println(o);
}
于 2013-09-22T18:11:49.533 回答