I'm in the process of adding multiplayer to my indie game by creating a server/client relationship using KryoNet. I started with a simple proof of concept which worked well. I've integrated it into the game up to the point where I have data transfering back and forth (using sendTCP()). This is when I noticed a fatal connection issue.
I first start the server, then start the client. The client connects to the server and data is exchanged as expected. I then close the client connection using client.stop() and reconnect with client.start() and client.connect(timeout, "127.0.0.1", 1337, 1338) once again. Everything works fine. However, if I close and then restart the client program entirely I am unable to connect to the server (which is still running).
This is the error on the client:
java.net.SocketTimeoutException: Connected, but timed out during UDP registration: /
127.0.0.1:1338 at com.esotericsoftware.kryonet.Client.connect(Client.java:186)
at com.esotericsoftware.kryonet.Client.connect(Client.java:110)
at com.zyin.game.Game.connectToServer(Game.java:439)
at com.zyin.game.gui.screen.ScreenMultiplayer.lambda$0(ScreenMultiplayer.java:42)
at com.zyin.game.gui.screen.Button.onMouseClicked(Button.java:318)
at com.zyin.game.gui.screen.Screen.onMouseClicked(Screen.java:144)
at com.zyin.game.MouseInputHandler.handleMouseInput(MouseInputHandler.java:59)
at com.zyin.game.Game.loop(Game.java:321)
at com.zyin.game.Game.run(Game.java:203)
at com.zyin.game.Game.main(Game.java:191)
This is the error on the server:
00:12 WARN: [kryonet] Error reading UDP from unregistered address: /
127.0.0.1:55408com.esotericsoftware.kryonet.KryoNetException: Error during deserialization.
at com.esotericsoftware.kryonet.UdpConnection.readObject(UdpConnection.java:89)
at com.esotericsoftware.kryonet.Server.update(Server.java:274)
at com.esotericsoftware.kryonet.Server.run(Server.java:356)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.esotericsoftware.kryo.KryoException: Buffer underflow.
at com.esotericsoftware.kryo.io.Input.require(Input.java:162)
at com.esotericsoftware.kryo.io.Input.readInt(Input.java:308)
at com.esotericsoftware.kryo.serializers.FieldSerializer$IntField.read(FieldSerializer.java:341)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:221)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:732)
at com.esotericsoftware.kryonet.KryoSerialization.read(KryoSerialization.java:58)
at com.esotericsoftware.kryonet.UdpConnection.readObject(UdpConnection.java:83)
... 3 more
The error is outputted once every 100ms until the timeout is reached.
If I change the connection to a TCP only connection isntead of also using UDP it works fine. I tried this by changing my connect statement to client.connect(timeout, "127.0.0.1", 1337).
I've attempted to debug through the KryoNet code and didn't notice anything blaringly wrong, but it's also hard to do it due to the multithreaded nature of the code, timeouts constantly being hit, and update() being called so frequently.
But looking through the code and the error thrown leads me to believe that the newly created TCP connection isn't creating an entry in Server.pendingConnections for the to-be-made UDP connection. Or the RegisterUDP packet is having an incorrect connectionID associated with it. Both of which I could not confirm by stepping through the code.
I am new to this networking stuff so it is possible I'm missing something simple. Right now my best guess is it either has something to do with KryoNet's threaded implementation, or the way I close the connection on the client.
I can post code samples by request, but won't post the whole project online.