尝试编写一个程序,允许客户端相互发送对象。我目前正在使用 ObjectOuptutStream 通过套接字发送它,每当我尝试从对象流中读取或写入对象时,它都会给出异常:java.io.NotSerializedException。我在网上搜索了有关此异常的信息,我得到的解决方案主要是在您正在发送或从流中读取的对象上实现 Serialized 接口(interface)。我这样做了,但仍然收到此异常。
这是对象类:
public class Event implements Serializable {
private static final long serialVersionUID = 1L;
Integer from;
Vector<Integer> timestamp;
public Event(int identifier, Vector<Integer> timestamp) {
this.from = identifier;
this.timestamp = timestamp;
}
int getFromID() {
return from;
}
Vector<Integer> getTimestamp() {
return timestamp;
}
}
这是写入其他套接字的 Client 类部分
Random rand = new Random();
int temp;
while (eventCount < 100) {
System.out.println("Generating Event");
int choice = rand.nextInt(5);
if (choice == 0) {
temp = timestamp.get(identifier);
++temp;
timestamp.set(identifier, temp);
} else {
int randC = rand.nextInt(outputClients.size());
ClientSocket cc = outputClients.get(randC);
cc.out.writeObject(new Event(identifier, timestamp));
}
System.out.println("Done Generating Event");
}
这是正在读取对象的线程
public class ClientConnection extends Thread {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
Random rand = new Random();
public ClientConnection(Socket s) {
this.socket = s;
try {
out = new ObjectOutputStream (socket.getOutputStream());
in = new ObjectInputStream (socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
// execute the event
private void executeEvent(int from, Vector<Integer> x) {
int temp;
synchronized (timestamp) {
for (int i = 0; i < timestamp.size(); ++i) {
if (x.get(i) > timestamp.get(i)) {
timestamp.set(i, x.get(i));
}
}
temp = timestamp.get(from);
++temp;
timestamp.set(from, temp);
}
}
@Override
public void run () {
while (true) {
System.out.println("Reading events");
if (!isAlive) {
break;
}
try {
Event event = (Event) in.readObject();
executeEvent(event.getFromID(), event.getTimestamp());
} catch (ClassNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(timestamp);
}
}
}
这是完整上下文的 Client 类(假设导入了所有适当的包)
public class Computer {
static final int MAX_SYSTEMS = 2; // MAX SYSTEMS
static Vector<Integer> timestamp = new Vector<Integer>();
static int[] timestamp1 = new int[MAX_SYSTEMS]; // Time-stamp
static int identifier; // Computer ID
static int eventCount = 0; // Event Counts
static boolean isAlive = true; // Check if the computer is alive
Socket sockToServer;
PrintWriter outputToServer;
BufferedReader inputFromServer;
String textFromServer;
ServerSocket ss;
static ArrayList<ClientSocket> outputClients = new ArrayList<ClientSocket>();
static ArrayList<ClientConnection> inputClients = new ArrayList<ClientConnection>();
Log log;
public static void main(String[] args) throws IOException {
new Computer("127.0.0.1", 8000);
}
public Computer(String hostname, int port) throws IOException {
// Instantiate server socket
int socketPort = port + identifier + 1;
System.out.println(socketPort);
ss = new ServerSocket(socketPort);
System.out.println("Server Socket Instantiated");
// Creating sockets (with streams) to write to stream
for (int i = 0; i < MAX_SYSTEMS; ++i) {
if (i != identifier) {
Socket thing1 = new Socket(hostname, port + i + 1);
ClientSocket cs = new ClientSocket (thing1);
outputClients.add(cs);
}
}
log.write("Client Sockets Instantiated\n");
// Create threads for reading objects and updating timestamp
for (int i = 0; i < MAX_SYSTEMS - 1; ++i) {
ClientConnection clientConn = new ClientConnection(ss.accept());
clientConn.start();
inputClients.add(clientConn);
}
log.write("Server connected to clients");
Random rand = new Random();
// Writing Events
int temp;
while (eventCount < 100) {
System.out.println("Generating Event");
int choice = rand.nextInt(5);
if (choice == 0) {
temp = timestamp.get(identifier);
++temp;
timestamp.set(identifier, temp);
} else {
int randC = rand.nextInt(outputClients.size());
ClientSocket cc = outputClients.get(randC);
cc.out.writeObject(new Event(identifier, timestamp));
}
System.out.println("Done Generating Event");
}
log.write("Computer finished generating events. Continue listening...\n");
outputToServer.println("Finish");
// Wait for Tear Down Message
while (true) {
try {
textFromServer = inputFromServer.readLine();
if (textFromServer.equals("Tear Down")) {
isAlive = false;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
log.write("Computer shutting off....");
for (int i = 0; i < outputClients.size(); ++i) {
ClientSocket sc = outputClients.get(i);
sc.socket.close();
}
sockToServer.close();
}
// client socket class (organizing)
public class ClientSocket {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
public ClientSocket(Socket s) {
try {
this.socket = s;
this.out = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Client Socket Created");
}
}
public class Event implements Serializable {
private static final long serialVersionUID = 1L;
Integer from;
Vector<Integer> timestamp;
public Event(int identifier, Vector<Integer> timestamp) {
this.from = identifier;
this.timestamp = timestamp;
}
int getFromID() {
return from;
}
Vector<Integer> getTimestamp() {
return timestamp;
}
}
// send event thread
public class ClientConnection extends Thread {
Socket socket;
ObjectOutputStream out;
ObjectInputStream in;
Random rand = new Random();
public ClientConnection(Socket s) {
this.socket = s;
try {
out = new ObjectOutputStream (socket.getOutputStream());
in = new ObjectInputStream (socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
// execute the event
private void executeEvent(int from, Vector<Integer> x) {
int temp;
synchronized (timestamp) {
for (int i = 0; i < timestamp.size(); ++i) {
if (x.get(i) > timestamp.get(i)) {
timestamp.set(i, x.get(i));
}
}
temp = timestamp.get(from);
++temp;
timestamp.set(from, temp);
}
}
@Override
public void run () {
while (true) {
System.out.println("Reading events");
if (!isAlive) {
break;
}
try {
Event event = (Event) in.readObject();
executeEvent(event.getFromID(), event.getTimestamp());
} catch (ClassNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(timestamp);
}
}
}
}
TL;DR 尝试使用 Object(Output/Input)Stream 对象通过套接字读取和写入对象。当我这样做时,我得到了 NotSerializedException,即使我在正在从流中写入和读取的类中实现了 Serialized 接口(interface)。
感谢所有帮助!
(编辑:堆栈跟踪)
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: timetableexchange.Computer
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
at java.io.ObjectInputStream.readSerialData(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at timetableexchange.Computer$ClientConnection.run(Computer.java:239)
Caused by: java.io.NotSerializableException: timetableexchange.Computer
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at timetableexchange.Computer.<init>(Computer.java:128)
at timetableexchange.Computer.main(Computer.java:39)
java.io.NotSerializableException: timetableexchange.Computer
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at timetableexchange.Computer.<init>(Computer.java:128)
at timetableexchange.Computer.main(Computer.java:39)
最佳答案
现在您已经提供了堆栈跟踪......我看到了问题!
您已将 Event
创建为 Computer
的内部类。这意味着 Event
具有到封闭的 Computer
实例的隐式链接...该实例将与 Event
实例一起序列化。
但是计算机
不是可序列化
。
一个(可能不正确的)解决方案是让Computer
实现Serialized
。但这意味着您将向每个单独序列化的 Event
发送一个 Computer
实例...这就是它可能是错误的原因。
更好的解决方案是将 Event
声明为 static
,这样它就不会引用封闭的计算机
。据我所知,它不需要是一个“内部”类。它可能只是一个“嵌套”类,甚至是一个顶级类。
建议:当您使用嵌套类和内部类时,请确保正确缩进它们......以便其他人更容易发现发生了什么。
关于java - 通过套接字流发送对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53365821/