简体   繁体   English

通过 TCP 套接字发送对象 - ClassNotFoundException

[英]Sending object through TCP socket - ClassNotFoundException

I have two simple applications: client and server.我有两个简单的应用程序:客户端和服务器。 Client encrypts (simple AES) custom object and sends it through TCP socket, as bytes, to the server.客户端加密(简单 AES)自定义对象并通过 TCP 套接字将其作为字节发送到服务器。 Server decrypts those bytes and calls the method that recreates this object, like this:服务器解密这些字节并调用重新创建此对象的方法,如下所示:

private static Object getObjectFromBytes(byte[] credentials) throws IOException,      ClassNotFoundException{

    ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
    ObjectInput in = null;
    Object credentialsObj = null;

    try {

        in = new ObjectInputStream(bis);
        credentialsObj = in.readObject(); 

    } finally {
      bis.close();
      in.close();
    }
    return credentialsObj;
}

On the client side, when I'am encrypting this object, it is of type mds.hm5.client.ITU_Credentials .在客户端,当我加密这个对象时,它的类型是mds.hm5.client.ITU_Credentials On the server side, when I'm decrypting it and converting back to object, it should be mds.hm5.tokenservice.ITU_Credentials .在服务器端,当我解密它并转换回对象时,它应该是mds.hm5.tokenservice.ITU_Credentials Instead I'am getting the following exception:相反,我收到以下异常:

java.lang.ClassNotFoundException: mds.hm5.client.ITU_Credentials

He is looking for this object by the old classpath.他正在通过旧的类路径寻找这个对象。 Why is it happening and how should I fix it?为什么会发生这种情况,我该如何解决?

Additional information:附加信息:

Here is how I convert this object to byte array on the client side:这是我在客户端将此对象转换为字节数组的方法:

private static byte[] getBytesFromObject(Object credentials) throws IOException{

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = null;
    byte[] newBytes = null;

    try {

      out = new ObjectOutputStream(bos);   
      out.writeObject(credentials);
      newBytes = bos.toByteArray();

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
      out.close();
      bos.close();
    }
    return newBytes;
}   

The reason why I use generic type Object is because I am going use those methods to convert/encrypt/decrypt multiple types.我使用泛型类型Object的原因是因为我将使用这些方法来转换/加密/解密多种类型。 Is it the proper way?这是正确的方法吗?

On the client side, when I'am encrypting this object, it is of type mds.hm5.client.ITU_Credentials.在客户端,当我加密这个对象时,它的类型是 mds.hm5.client.ITU_Credentials。

So that's what it is in the serialized stream.这就是序列化流中的内容。

On the server side, when I'm decrypting it and converting back to object, it should be mds.hm5.tokenservice.ITU_Credentials.在服务器端,当我解密它并转换回对象时,它应该是 mds.hm5.tokenservice.ITU_Credentials。

No it shouldn't.不,不应该。 It should be the same as when you serialized it [unless you have taken certain magic steps, which clearly you haven't.它应该和你连载时一样[除非你采取了某些神奇的步骤,而这显然是你没有的。 Without those magic steps there is no magic, and nothing to connect mds.hm5.client.ITU_Credentials with mds.hm5.tokenservice.ITU_Credentials whatsoever].没有这些神奇的步骤,就没有魔法,也没有什么可以将mds.hm5.client.ITU_Credentialsmds.hm5.tokenservice.ITU_Credentials连接mds.hm5.client.ITU_Credentials ]。 You have two different classes with the same name and different packages, one in each location.您有两个具有相同名称和不同包的不同类,每个位置一个。 They aren't the same.他们不一样。

He is looking for this object by the old classpath.他正在通过旧的类路径寻找这个对象。

You are confused between CLASSPATH and package name.您对 CLASSPATH 和包名感到困惑。 They aren't the same thing.它们不是一回事。 It is looking for this object by its actual package name.它正在通过它的实际包名称寻找这个对象 What else can it possibly do?它还能做什么?

The object output stream doesn't serialize the class itself but only its state (the field values).对象输出流不会序列化类本身,而只会序列化它的状态(字段值)。 The receiver needs the class file on it's classpath.接收器需要类路径上的类文件。

It is possible to transfer the class too.也可以转课。 You'll have to find (or write) a classloader that can load the class from your connection.您必须找到(或编写)一个可以从您的连接加载类的类加载器。 If you have an URL for your classfile then you could use the URLClassloader.如果您有类文件的 URL,那么您可以使用 URLClassloader。 Then you don't have to add the class to your classpath.然后您不必将该类添加到您的类路径中。

Your client neeeds to have in its classpath the .class files that define the object.您的客户端需要在其类路径中包含定义对象的 .class 文件。 What you are doing is serializing/deserializing the instance, not the class.您正在做的是序列化/反序列化实例,而不是类。

Late, but it may be useful for someone in the future: I wanted to send an object Message whose package was entities in the client side, but in the server side this Message class was not nested within a entities package, so this Exception was thrown.晚了,但它可能对将来的某人有用:我想发送一个对象Message,其包是客户端的实体,但在服务器端,此Message类未嵌套在实体包中,因此抛出此异常. It may be dumb but I spent many hours figuring out this.这可能很愚蠢,但我花了很多时间弄清楚这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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