我试图绕过 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
P.S。我不知道是否必须要做一些事情来序列化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
答案 0 :(得分:1)
您正在读取对象两次,但仅第二次打印。 因此,当您尝试第二次读取时,客户端可能会关闭,因此套接字已在远程端关闭,因此例外。
您正在读取!= null检查中的对象。你不打印它。然后你试着再次读它并炸弹。
从流中读取后,它已被阅读。它是一个流,而不是缓冲区。您可能希望缓冲读取,然后您可以根据需要检查该缓冲区。
最简单的例子......
Object o = outputStream.readObject();
if(o != null) {
system.out.println(o);
}
答案 1 :(得分:1)
这是因为客户端套接字在执行完所有代码后自动终止。
例如,如果添加
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;
}
}