Slick2D KryoNet Applet

时间:2013-02-27 05:22:41

标签: networking kryonet

我正在使用Kryonet和Slick2d制作一个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运行,客户端applet在本地的HTML文件中运行,运行xampp作为Web服务器。

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

任何帮助/建议都会非常感激 - 我已经被遗忘了一段时间了! 感谢

2 个答案:

答案 0 :(得分:0)

我在gradle构建中遇到类似的问题。可能只需要为applet JVM增加内存(堆或PermSize)

答案 1 :(得分:0)

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

要更改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具有与嵌入式applet相同的行为。这不是一个完整的解决方案,但可以帮助找到问题的原因。

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

1)使用其他序列化程序。默认值为FieldSerializer,可以使用

进行更改
public void setDefaultSerializer (Class<? extends Serializer> serializer)

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

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

    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) {
        }
    }

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