I’m a little uncertain about how to correctly shut down a nonblocking socket.
Here’s my setup:
1 thread handles selecting for all clients:
New accepted channels are wrapped in “PlayerConnection” objects and put on a queue for the gameloop to fetch.
These channels are also registered with the selector for OP_READ
The PlayerConnection object is attached to the channels key
Read data is handled by the PlayerConnection object, that builds messages according to my protocol and puts them on a queue (Unfinished messages are no problem, as I’m using state-based parsing)
Another thread handles the gameloop
Fetches new PlayerConnection objects from the connection queue - attached them to new Player object and enters them into the game.
Fetches new messages from the client queues - acts on them.
My problem is: What is the right way to shut the sockets down?
I remove the Player objects (and with them their associated Connection objects) from the game model.
Then I try to shut them down like this:
public void stop()
{
System.out.println("stop");
//connected = false;
Socket sock = channel.socket();
//close the input stream to cause an exception in the read method
try
{
sock.shutdownOutput();
} catch (Exception e)
{
e.printStackTrace();
}
try
{
sock.shutdownInput();
} catch (Exception e)
{
e.printStackTrace();
}
try
{
channel.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
It seems to be working alright, as the clients detect the closed socket and acts correctly.
My problem is: What happens to the selection keys? Are they still registered with the selector after this?
If so then this could be a possible memory leak, as the inactive Player and PlayerConnection objects are referenced by those keys and never gets garbage-collected.
Any idea what happens here?
Also, is shutdownInput and shutdownOutput required? Or does Channel.close() do that for me?