1

我正在使用带有 Slick2d 的 Kryonet 来制作 Java 游戏。

作为java应用程序运行时它工作正常,但是作为applet运行时我收到以下错误:

00:00  INFO: [kryonet] Server opened.
00:04 DEBUG: [kryonet] Port 9991/TCP connected to: /(ip):55801
00:04 DEBUG: [kryo] Write: RegisterTCP
00:04  INFO: [kryonet] Connection 1 connected: /(ip)
00:04  INFO: [SERVER] Someone has connected.
00:04 ERROR: [kryonet] Error reading TCP from connection: Connection 1
com.esotericsoftware.kryonet.KryoNetException: Error during deserialization.
    at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:141)

    at com.esotericsoftware.kryonet.Server.update(Server.java:192)
    at com.esotericsoftware.kryonet.Server.run(Server.java:350)
    at java.lang.Thread.run(Unknown Source)
Caused by: com.esotericsoftware.kryo.KryoException: Buffer underflow.
    at com.esotericsoftware.kryo.io.Input.require(Input.java:162)
    at com.esotericsoftware.kryo.io.Input.readLong(Input.java:621)
    at com.esotericsoftware.kryo.io.Input.readDouble(Input.java:745)
    at com.esotericsoftware.kryo.serializers.DefaultSerializers$DoubleSerializer.read(DefaultSerializers.java:141)
    at com.esotericsoftware.kryo.serializers.DefaultSerializers$DoubleSerializer.read(DefaultSerializers.java:131)
    at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:735)
    at com.esotericsoftware.kryonet.KryoSerialization.read(KryoSerialization.java:57)
    at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:139)
    ... 3 more
00:04  INFO: [SERVER] Someone has disconnected.
00:04  INFO: [kryonet] Connection 1 disconnected.

服务器在本地作为可运行的 jar 运行,客户端小程序也在本地以 HTML 文件形式运行,它运行 xampp 以充当 Web 服务器。

我尝试了不同的序列化程序、缓冲区大小和只发送单个字符串/布尔值等,它似乎不喜欢任何东西。客户端连接到服务器非常好,但是在发送任何数据包时,无论发送什么数据包,我都会收到上述错误。

任何帮助/建议将不胜感激 - 我已经为此困扰了一段时间!谢谢

4

2 回答 2

0

我在 gradle build 中有类似的问题。可能您只需要为小程序 JVM 增加内存(堆或 PermSize)

于 2013-03-07T12:08:35.673 回答
0

我相信我有同样的问题或至少类似的问题。我将 Kryonet 用于服务器和客户端。客户端是一个小程序,当我通过 Eclipse 的 Applet 查看器运行它时,它运行良好。当我通过 Web 服务器运行它时,我会遇到类似的错误。客户端和服务器连接,服务器接收客户端的数据包,但客户端在尝试任何反序列化时都会出错。我发现小程序权限是罪魁祸首。如果您将 Applet Viewer(如果您使用 Eclipse)的权限更改为与网页相同,您将得到相同的错误。优点是您可以随后调试问题。

要更改 Eclipse 的权限: 转到您的项目文件夹 \bin\ 并打开“java.policy.applet”。在里面你应该有:

grant {
  permission java.security.AllPermission;
};

将其更改为:

grant {
    permission java.io.FilePermission "<<ALL FILES>>", "read, write, execute, delete";  
    permission java.net.SocketPermission "*", "accept, connect, listen, resolve";  
    permission java.util.PropertyPermission "*", "read, write";  
    permission java.lang.RuntimePermission "*";  
    permission java.awt.AWTPermission "showWindowWithoutWarningBanner";  
};

通过这个更改,Applet Viewer 的行为与嵌入式小程序相同。这不是一个完整的解决方案,但可以帮助找到问题的原因。

更新:我发现我的情况有什么问题。问题出在 FieldSerializer 和使用它的其他序列化程序中。当一个类被注册时,FieldSerializer 会遍历它的字段并将它们全部设置为可访问。小程序不允许此操作。结果是错误的注册和序列化/反序列化。我找到了 2 个解决方法:

1) 使用另一个序列化程序。默认值是 FieldSerializer,可以使用更改

public void setDefaultSerializer (Class<? extends Serializer> serializer)

另一种选择是在注册每个类时设置序列化程序。不要使用基于 FieldSerializer 的序列化程序。

2)尝试修复FieldSerializer。我所做的并不完全正确,但它适用于我的情况。如果可访问性设置导致异常,我们将使 FieldSerializer 继续注册。我们需要做的另一件事是将我们注册的类的所有字段设置为公开。要更改 FieldSerializer,您需要 Kryo 源。转到 FieldSerializer.java,重建CachedFields()。您将在那里找到以下代码:

    if (!field.isAccessible()) {
        if (!setFieldsAsAccessible) continue;
        try {
            field.setAccessible(true);
        } catch (AccessControlException ex) {
            continue;
        }
    }

您需要将其更改为:

    if (!field.isAccessible()) {
        if (setFieldsAsAccessible)
        try {
            field.setAccessible(true);
        } catch (AccessControlException ex) {
        }
    }

需要更改的另一件事是所有已注册的类都只有公共字段。

于 2013-03-08T17:18:46.050 回答