The worst thing that you could do is set all of your sockets to non-blocking. This will create an idle loop, where your WS server will constantly check everything, will eat through your CPU time, accomplish nothing meaningful, and make people mad at you.
The next worst thing is to block indefinitely. This will require clients to periodically send data, chewing through bandwidth, accomplish nothing meaningful, possibly put your server in a hung state while there are no clients connected, and make people mad at you.
Instead, use blocking, but set a timeout. This is a balancing act that depends on your system, and only you can decide the duration of the timeout, hopefully with a bit of data to back up your decision.
The best place to put a timeout is socket_select()
. The code below will wait for a maximum of 1 second for new packets to come in, and when it gets bored, it'll do your DB stuff.
define("SOCKET_TIMEOUT", 1);
function tick() { /* Put your DB checking here. */ }
while (true) {
$read = get_array_of_sockets_that_may_have_sent_a_packet();
$write = $except = null; // We probably don't care about these.
tick();
$number_of_sockets_ready = socket_select($read, $write, $except, SOCKET_TIMEOUT);
if ($number_of_sockets_ready === false) { ... } /* Something went horribly wrong. socket_strerror(socket_last_error()) is your friend here. */
elseif ($number_of_sockets > 0) {
// At least one socket is ready for socket_recv() or socket_read(). Do your magic here!
}
}
Note that the timeout does not guarantee that tick()
will be called every second, or only once per second. If a packet comes in immediately, and is handled trivially, it could potentially only be a few milliseconds between calls to tick()
. On the other hand, if several packets come in and it's not trivial to handle each one, then it could be several seconds before tick()
gets called again.