[英]Sending objects through socket streams
Trying to write a program that will allow clients to send an object to each other. 尝试编写一个程序,该程序将允许客户端彼此发送对象。 I'm currently using the ObjectOuptutStream to send it across sockets and whenever I try to read or write an object from the object stream, it gives the exception: java.io.NotSerializableException .
我目前正在使用ObjectOuptutStream跨套接字发送它,并且每当我尝试从对象流中读取或写入对象时,都会产生异常: java.io.NotSerializableException 。 I searched online about this exception, and the solution I am getting mostly was to implement the Serializable interface on the object you are sending or reading from the stream.
我在网上搜索了有关此异常的信息,得到的主要解决方案是在要从流发送或读取的对象上实现Serializable接口。 Which I did, but still receives this exception.
我做到了,但仍然收到此异常。
Here's the object class: 这是对象类:
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;
}
}
Here's the section of the Client class that is writing to other sockets 这是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");
}
And here's the threads that are reading the object 这是正在读取对象的线程
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);
}
}
}
And here's the Client class for full context (assuming all the appropriate packages are imported) 这是用于完整上下文的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 Trying to read and write object through sockets using Object(Output/Input)Stream object. TL; DR尝试使用Object(Output / Input)Stream对象通过套接字读取和写入对象。 When I do so, I get the NotSerializableException, even though I implemented the Serializable interface in the class that was being written and read from the stream.
这样做时,即使我在要从流中读写的类中实现了Serializable接口,也得到了NotSerializableException。
All help is appreciated! 感谢所有帮助!
(edit: stacktrace) (编辑:stacktrace)
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)
Now that you have supplied the stacktrace .... I see the problem! 现在,您已经提供了stacktrace...。我看到了问题!
You have created Event
as an inner class of Computer
. 您已将
Event
创建为Computer
的内部类。 That means that an Event
has an implicit link to the enclosing Computer
instance ... which will be serialized along with the Event
instance. 这意味着一个
Event
具有到封闭的Computer
实例的隐式链接...,该隐式链接将与Event
实例一起序列化。
But Computer
is not Serializable
. 但是
Computer
不能Serializable
。
A (probably incorrect) solution would be to make Computer
implement Serializable
. 一个(可能不正确的)解决方案是使
Computer
实现Serializable
。 But that means you would send an instance of Computer
with every separately serialized Event
... which is why it is probably wrong. 但这意味着您将向每个单独的序列化
Event
发送一个Computer
实例...这就是为什么它可能是错误的。
A better solution would be to declare Event
as static
so that it doesn't have a reference to the enclosing Computer
. 更好的解决方案是将
Event
声明为static
以便它没有对封闭的Computer
的引用。 As far as I can see, it doesn't need to be an "inner" class. 据我所知,它不必是“内部”类。 It could just be a "nested" class, or even a top-level class.
它可能只是一个“嵌套”类,甚至是一个顶级类。
Advice: When you use nested and inner classes, make sure that you indent them correctly ... to make it easier for other people to spot what is going on. 建议:使用嵌套类和内部类时,请确保正确缩进它们...以使其他人更容易发现正在发生的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.