如何使用Kryonet通过网络发送对象?

时间:2014-03-26 22:47:59

标签: networking kryonet

我是网络新手,我正在尝试建立一个我用java创建的棋盘游戏。我的一个朋友向我指出了Kryonet库。到目前为止,这很棒。我不必处理套接字!

我遇到的问题是发送对象。主要是,我有一个Board类型的对象。该对象包含其他对象,例如ArrayList对象和Fort对象。

我尝试注册Board对象,但收到了这些错误:

Exception in thread "Server" com.esotericsoftware.kryo.KryoException: java.lang.
IllegalArgumentException: Class is not registered: Game.Tile
Note: To register this class use: kryo.register(Game.Tile.class);
Serialization trace:
t0 (Game.Board)
        at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:585)
        at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
        at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:571)    
    at com.esotericsoftware.kryonet.KryoSerialization.write(KryoSerializatio
n.java:50)
    at com.esotericsoftware.kryonet.TcpConnection.send(TcpConnection.java:192)
        etc....

好的,那我也会注册Tile.class,

更多错误,但后来我需要注册ArrayList.class - 所以我注册了它,再次出现更多错误,所以我注册了Fort.class。

当我注册Fort.class时,我进入一个无限循环并得到大量的错误:

    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:504)
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
    at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
    at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:504)
    at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)

这让我相信我不太了解如何正确注册,我找不到有关如何注册嵌套对象的更多信息。我的Fort类实际上是一个枚举类,但我不确定这是否有所作为?任何帮助将不胜感激!

我已经包含了一个包含大部分网络代码的课程,因此您可以看到我想要做的事情。

这是我的网络代码:

public class Network extends Listener {
    private Server server;
    private Client client;
    private boolean isServer;
    private boolean messageReceived;
    private PacketMessage message;
    private Board board;

    public Network(boolean isServer, Board board) throws IOException {
        messageReceived = false;
        this.board = board;
        this.isServer = isServer;
        if (isServer) {
            initServer();
            // receive();
        } else {
            initClient();
            //probably want to run this in main
            client();
        }
    }

    private void initServer() throws IOException {
        // 127.0.0.1 means myself
        // ports up to 1024 are special and reserved
        server = new Server();
        registerClasses(server.getKryo());
        server.bind(8000, 8001);
        // starting a new thread
        server.start();
        // call my received and my connected
        server.addListener(this);
    }

    private void initClient() throws IOException {
        // 127.0.0.1 means myself
        // ports up to 1024 are special and reserved
        client = new Client();
        registerClasses(client.getKryo());
        // starting a new thread
        client.start();
        client.connect(5000, "127.0.0.1", 8000, 8001);
        // call my received and call my connected
        client.addListener(this);

    }

    //call in main
    //
    public void client(){
        while(true){
            sendRequest();
            receive();
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    // tell Kryo what things it's going to have to send
    private void registerClasses(Kryo kryo) {
        kryo.register(Request.class);
            kryo.register(PacketMessage.class);
        kryo.register(Fort.class);
        kryo.register(ArrayList.class);
        kryo.register(Tile.class);
        kryo.register(Board.class);
    }

    private void sendRequest() {
        client.sendTCP(new Request());
    }

    private void receive() {
        messageReceived = false;
        while (!messageReceived) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        // message.message is really packet.message
        System.out.println("Received a message from the host: "
                + message.message);
    }

    public void received(Connection c, Object p) {
        System.out.println("Received Message");

        // Is the received packet the same class as PacketMessage.class?
        if (p instanceof PacketMessage) {
            // Cast it so we can access the message within
            // PacketMessage packet =(PacketMessage) p;
            // System.out.println("Received a message from the host: "+pa    cket.message);
            message = (PacketMessage) p;
            // We have now received the message!
            messageReceived = true;
        }
        else if (p instanceof Request){
            // Create a message packet
            PacketMessage packetMessage = new PacketMessage();
            // Assign the message text
            packetMessage.message = "Hello friend!  The time is: "
                    + new Date().toString();

            // Send the message
            //probably want another method to send
            c.sendTCP(packetMessage);
            c.sendTCP(board);
        }
    }

    // This is run when a connection is received!
    public void connected(Connection c) {
        System.out.println("Received a connection from "
                + c.getRemoteAddressTCP().getHostString());

    }

}

1 个答案:

答案 0 :(得分:0)

可能发生的事情是你的Fort类包含一个Board类型的成员,这个循环引用在序列化Fort时会产生无限循环。

使用transient关键字从序列化中排除成员,或完全删除循环引用。