3

I am new to networking, and I am trying to network a board game that I have created using java.A friend of mine pointed me towards the Kryonet library. So far, it's great. I don't have to deal with sockets!

The problem I'm coming across is sending objects. Mainly, I have a Board type object. This object contains other objects, such as ArrayList objects and Fort objects.

I tried just registering the Board object, but I received these errors:

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....

Ok fine, Then I will also register Tile.class,

More errors, but then I need to register ArrayList.class - so I register it, and again more errors, so I register Fort.class.

When I register Fort.class, I enter into an infinite loop and get a ton of errors like this:

    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)

This leads me to believe I don't quite understand how to register properly and I can't find much information about how to register nested objects. My Fort class is actually an enumerated class but I'm not sure if that makes a difference? Any help would be greatly appreciated!

I have included a class with most of my networking code so you can see an idea of what I am trying to do.

This is my code for the networking:

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());

    }

}
Sarah
  • 2,713
  • 13
  • 31
  • 45

1 Answers1

0

What is likely happening is that your Fort class contains a member of type Board, and this circular reference causes an infinite loop when serializing Fort.

Use the transient keyword to exclude members from serialization, or remove the circular reference altogether.

colti
  • 393
  • 1
  • 15
  • It's not a circular reference as far as I can see, maybe it's because Fort is an enum class, any idea on how to register an enum? – Sarah Mar 29 '14 at 13:48