Java SocketException:使用 ObjectInputStream 在服务器上重置连接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18947088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 12:49:22  来源:igfitidea点击:

SocketException: Connection reset on server with ObjectInputStream

javasocketsclient-serverobjectinputstreamobjectoutputstream

提问by akafortes

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.

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

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.

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

EDIT after Aaron answerI 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

采纳答案by Aaron

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.

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

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

回答by Cristian Traìna

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