2

I have this small piece of code in my class which extends Listener:

@Override
public void received(Connection connection, Object object)
{
    Packet packet = (Packet) object;
    server.addPacket(new ClientPacket(connection.getID(), packet));
}

Whenever I receive an Object, I cast it to an Interface called Packet with a method handle() which every packet implement. I then add it to a ConcurrentLinkedQueue for future processing.

Still, after i spam a few keys which send UDP packets to the server, the following Exception is thrown:

Exception in thread "Server" java.lang.ClassCastException: com.esotericsoftware.kryonet.FrameworkMessage$KeepAlive cannot be cast to com.xkynar.game.net.packet.Packet at com.xkynar.game.net.ServerSocket.received(ServerSocket.java:70) at com.esotericsoftware.kryonet.Server$1.received(Server.java:61) at com.esotericsoftware.kryonet.Connection.notifyReceived(Connection.java:246) at com.esotericsoftware.kryonet.Server.update(Server.java:208) at com.esotericsoftware.kryonet.Server.run(Server.java:356) at java.lang.Thread.run(Unknown Source)

The exception occurs in the cast, that is:

Packet packet = (Packet) object;

How can this be possible? What the hell is "FrameworkMessage$KeepAlive" to begin with? Why is it entering my received listener?

Please explain what is wrong, is it my mistake or a bug?

Xkynar
  • 935
  • 1
  • 10
  • 31

3 Answers3

1

The problem was Kryonet often sends packets without my knowledge to not close the connection (KeepAlive packet in this case), so the solution is to do an instanceof check:

@Override
public void received(Connection connection, Object object)
{   
    if(object instanceof Packet)
        server.addPacket(new ClientPacket(connection.getID(), (Packet) object));
}
Xkynar
  • 935
  • 1
  • 10
  • 31
0

FrameworkMessage is an interface that is used to mark objects as being used internally to the framework. From the documentation:

public interface FrameworkMessage

Marker interface to denote that a message is used by the Ninja framework and is generally invisible to the developer. Eg, these messages are only logged at the Log.LEVEL_TRACE level.

It's safe to assume that your code may not be the only listener to a server. The solution is to check object's identity at run time. This is illustrated in the kryonet readme:

server.addListener(new Listener() {
    public void received (Connection connection, Object object) {
        if (object instanceof SomeRequest) {
            SomeRequest request = (SomeRequest)object;

In your code, you'd replace SomeRequest with Packet in the above snippet.

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
0

In kryonet, the server keeps sending KeepAlive objects so that he client don't disconnect due to a timeout occuring because a timeout occurs when a client don't receive any message from Server for a provided period of time and hence to avoid this the server keeps sending KeepAlive objects which are nothing but empty objects.

So inside your received, other than your objects you will also receive KeepAlive object packets.

To solve this issue you have to first check whether an object is instance of the class you are trying to cast the object into.

So in your case you need to do

 if(object instanceof Packet)
        server.addPacket(new ClientPacket(connection.getID(), (Packet) object));
Sneh
  • 3,527
  • 2
  • 19
  • 37