简体   繁体   English

通过套接字流发送对象

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM