通过套接字流发送对象
Sending objects through socket streams
正在尝试编写一个允许客户端相互发送对象的程序。我目前正在使用 ObjectOuptutStream 跨套接字发送它,每当我尝试从对象流读取或写入对象时,它都会给出异常:java.io.NotSerializableException。我在网上搜索了有关此异常的信息,我得到的解决方案主要是在您正在发送或从流中读取的对象上实现 Serializable 接口。我这样做了,但仍然收到此异常。
这是对象 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;
}
}
这是客户端 class 正在写入其他套接字的部分
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);
}
}
}
这里是完整上下文的客户端 class(假设导入了所有适当的包)
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 对象通过套接字读写对象。当我这样做时,我得到了 NotSerializableException,即使我在正在写入和从流中读取的 class 中实现了 Serializable 接口。
感谢所有帮助!
(编辑:堆栈跟踪)
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
的内部 class。这意味着 Event
对封闭的 Computer
实例有一个隐含的 link ...它将与 Event
实例一起序列化。
但是 Computer
不是 Serializable
。
一个(可能不正确的)解决方案是使 Computer
实现 Serializable
。但这意味着您将发送一个 Computer
的实例,每个单独序列化 Event
...这就是为什么它可能是错误的。
更好的解决方案是将 Event
声明为 static
,这样它 就不会 引用封闭的 Computer
.据我所知,它不需要是 "inner" class。它可能只是 "nested" class,甚至是顶级 class.
建议:当您使用嵌套和内部 classes 时,请确保正确缩进它们...以便其他人更容易发现正在发生的事情。
正在尝试编写一个允许客户端相互发送对象的程序。我目前正在使用 ObjectOuptutStream 跨套接字发送它,每当我尝试从对象流读取或写入对象时,它都会给出异常:java.io.NotSerializableException。我在网上搜索了有关此异常的信息,我得到的解决方案主要是在您正在发送或从流中读取的对象上实现 Serializable 接口。我这样做了,但仍然收到此异常。
这是对象 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;
}
}
这是客户端 class 正在写入其他套接字的部分
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);
}
}
}
这里是完整上下文的客户端 class(假设导入了所有适当的包)
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 对象通过套接字读写对象。当我这样做时,我得到了 NotSerializableException,即使我在正在写入和从流中读取的 class 中实现了 Serializable 接口。
感谢所有帮助!
(编辑:堆栈跟踪)
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
的内部 class。这意味着 Event
对封闭的 Computer
实例有一个隐含的 link ...它将与 Event
实例一起序列化。
但是 Computer
不是 Serializable
。
一个(可能不正确的)解决方案是使 Computer
实现 Serializable
。但这意味着您将发送一个 Computer
的实例,每个单独序列化 Event
...这就是为什么它可能是错误的。
更好的解决方案是将 Event
声明为 static
,这样它 就不会 引用封闭的 Computer
.据我所知,它不需要是 "inner" class。它可能只是 "nested" class,甚至是顶级 class.
建议:当您使用嵌套和内部 classes 时,请确保正确缩进它们...以便其他人更容易发现正在发生的事情。