【问题标题】:SocketException: Connection reset on server with ObjectInputStreamSocketException:使用 ObjectInputStream 在服务器上重置连接
【发布时间】:2013-09-22 18:05:10
【问题描述】:

我试图了解 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

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

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

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

【问题讨论】:

    标签: java sockets client-server objectinputstream objectoutputstream


    【解决方案1】:

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

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

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

    最简单的例子……

    Object o = outputStream.readObject();
    if(o != null) {
     system.out.println(o);
    }
    

    【讨论】:

    • 是的。关键是要记住流没有被缓冲。一旦你读了它,它就消失了。
    • 我不小心删除了我的评论。非常感谢您的澄清。
    • @akafortes 就像你打开啤酒水龙头时一样——你可以打开啤酒看看是否还有啤酒,但除非你用玻璃杯接住溢出的啤酒,否则你不能说“太好了,有啤酒”,然后在测试是否有啤酒时尝试喝你已经洒过的啤酒。
    • 应该是这样的“outputStream”还是一个错字,你的意思是写“inputStream”?
    • @akafortes 是的,对不起。输入流。
    【解决方案2】:

    发生这种情况是因为客户端套接字在其所有代码执行后自动终止。

    例如,如果你添加

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

    在您的客户端代码结束时,您不会得到任何连接重置,因为您的客户端套接字永远不会被终止。

    因此,客户端套接字已关闭,服务器端套接字必须处理此异常。 当你得到这个异常时,你应该退出循环,所以:

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

    【讨论】:

      猜你喜欢
      • 2013-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      相关资源
      最近更新 更多