为什么我使用 ObjectInputStream.readObject() 得到 ClassNotFoundException?

Why am I getting ClassNotFoundException with ObjectInputStream.readObject()?

以下客户端代码接受来自服务器的 "Guest" 对象:

protected static void sendLoginRequest(String email, String password) {
    try(
        Socket socket = new Socket("127.0.0.1", 44444);
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    ){
        out.write("LGNR");
        out.flush();
        out.newLine();
        out.flush();

        out.write(email);
        out.flush();
        out.newLine();
        out.flush();            

        out.write(password);
        out.flush();
        out.newLine();
        out.flush();

        in.ready();
        switch(in.readLine()) {
        case "SU":
            Guest g = null;
            try(ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());){
                g = (Guest) ois.readObject();
            }catch(ClassNotFoundException | IOException e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
            GuestProfileMenu.generateMenu(g);
            break;
        case "WP":
            System.out.println("Invalid Password.");
            break;
        case "IE":
            System.out.println("Email not found.");
            break;
        }

    }catch(IOException e) {
        System.out.println("No response from Server.");
        System.out.println(e.getMessage());
    }
}

在服务器端看起来像这样:

private void userLogin(Socket socket, BufferedReader in, BufferedWriter out) {
    System.out.println(socket.getInetAddress().getHostName() + ":" + socket.getLocalPort() + " - has sent a login request.\r\n");

    FileManager.openGuestFile();
    ArrayList<Guest> gList = FileManager.getGuestList();

    try{
        in.ready();
        String email = in.readLine();
        System.out.println(socket.getInetAddress().getHostName() + ":" + socket.getLocalPort() + " - Email received as: " + email);

        in.ready();
        String password = in.readLine();
        System.out.println(socket.getInetAddress().getHostName() + ":" + socket.getLocalPort() + " - Password received as: " + password);

        boolean exists = false;

        for(int i = 0; i < gList.size(); i++) {
            if (email.equals(gList.get(i).getEmail())) {
                exists = true;
                if (password.equals(gList.get(i).getPassword())) {                      
                    out.write("SU");
                    out.flush();
                    out.newLine();
                    out.flush();
                    try(ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());){            
                        oos.writeObject(gList.get(i));
                        oos.flush();
                    }catch(IOException e) {
                        System.out.println(e.getMessage());
                    }
                }else{
                    out.write("WP");
                    out.flush();
                    out.newLine();
                    out.flush();
                }
            }
        }
        if(!exists) {
            out.write("IE");
            out.flush();
            out.newLine();
            out.flush();
        }
        socket.close();
    }catch(IOException e) {
        System.out.println(e.getMessage());
    }

}

从客户端 returns ClassNotFoundException 在行 "g = (Guest) ois.readObject();":

java.lang.ClassNotFoundException: server.Guest
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at java.io.ObjectInputStream.resolveClass(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)

错误消息说 "server.Guest" 的事实,即 (class package).(object),我可以假设服务器的 Guest class 的实例不是与客户端的 Guest class 实例一样吗?那么如何通过套接字正确发送接收对象?

谢谢

The fact that the error message says "server.Guest", ie (class package).(object), can I assume that an instance of the server's Guest class isn't the same thing as an instance of the client's Guest class?

涉及到两个独立的 classes 是异常告诉你的,是的。

So how do I properly send a receive objects through a socket?

将自己限制在客户端和服务器都知道的 classes。有多种方法可以实现这一点,但它们几乎都涉及在连接的两端部署相同或等效的 .class 文件。 "Equivlent" 这里表示大约 "compiled from the same source with compilers of the same version".