SwammiM
SwammiM

Reputation: 493

Websockets - does a custom queueing system make sense?

I'm writing a node.js websocket back-end for a turn-based Unity game. This is my first time using node.js and websockets, so I figured I'd make it so that a player can reconnect, and will get any messages they missed.

Then I started implementing it in the game, and wanted to test my queueing system, so I turned off my internet connection and turned it back on - and was surprised to find that the connection survived this, and any missed messages were sent through the same connection. No need to reconnect and send the backlog to the new connection.

So it seems like the websocket technology already handles offline queueing? Does it even make sense to complicate the server code by doing this myself (and adding to the memory load of the server by keeping the messages in there)?

Also, how can it keep a socket connection alive without internet connection? Is there a standardized timeout for it, or will both parties keep track of it unless I close it manually?

Thanks!

Upvotes: 2

Views: 2108

Answers (1)

jfriend00
jfriend00

Reputation: 707466

Then I started implementing it in the game, and wanted to test my queueing system, so I turned off my internet connection and turned it back on - and was surprised to find that the connection survived this, and any missed messages were sent through the same connection. No need to reconnect and send the backlog to the new connection.

Turning off a connection does not automatically kill any sockets that were established over that connection. sockets will eventually get closed when they unsuccessfully try to send data and, after a number of retries and time passage, all they get is errors. If a socket is not actively trying to send any data and does not have any sort of keep-alive configured that might do that automatically, then it may sit there for hours with a dead connection and simply not know the connection is dead. As long as the socket is not being used, there's no automatic way it even knows that it's end-to-end connection is no longer functioning. It is only when it tries to use the connection and gets an error that it would figure that out.

Note, things would be different if the server process crashed, but the connection stayed alive. In that case, the TCP stack on the server would see that the server process crashes and would attempt to clean up any sockets that it was using and would send close packets to the other end and the other end would be proactively told that the socket was closed. But, your case of just disrupting the transport does not do the same.

So it seems like the websocket technology already handles offline queueing? Does it even make sense to complicate the server code by doing this myself (and adding to the memory load of the server by keeping the messages in there)?

A websocket is a protocol layer on top of a TCP socket. TCP is meant to be a reliable transport which means that when it has trouble sending data (but has not received any sort of notification that the socket has been closed by the other end), it hangs on to that data and retries. It will eventually give up and communicate back some error.

You may be interested in socket.io which is a layer on top of webSocket. It adds a couple things that are relevant here:

  1. Regular ping from end-to-end so it will know when the transport has been interrupted.
  2. Seamless auto-reconnect when the socket is closed or the transport is interrupted.
  3. Automatic queuing of data sent while the connection is temporarily interrupted.

Also, how can it keep a socket connection alive without internet connection? Is there a standardized timeout for it, or will both parties keep track of it unless I close it manually?

As I said earlier, if neither end is attempting to send data and the internet connection is interrupted somewhere in the middle between the two endpoints, then the webSocket may simply not know that the connection is currently not functional. The only way to regularly know whether the connection is functional is to send data across the connection and see if you get a timely response. This is what socket.io does with its ping/pong messages.

The way to keep a logical connection alive no matter what happens to the physical connection is to use an extra layer on top of the physical connection (like socket.io does on top of webSocket). This then allows you to have code that might restart the physical connection without changing your logical connection. This is exactly what socket.io does from the client side of things. If you wanted something similar from the server-side of things, you would probably need to implement your own queue of data that you want to send to a client and only remove things from the queue when you are sure they have been successfully sent.

Upvotes: 4

Related Questions