I am using ReactPHP for TCP listener component. This component listens for incoming connections and exchanges data with them. $connections array is updated as clients connect/disconnect from listener.
$loop = React\EventLoop\Factory::create();
$connections = [];
$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn) use($loop, $db){
global $connections;
$connections[] = $conn;
$conn->on('data', function ($data) use ($conn,$loop, $db) {
global $connections;
// ...
// ...
$conn->on('close', function ($conn) use($loop, $db){
global $connections;
if(($key = array_search($conn, $connections, true)) !== FALSE) {
unset($connections[$key]);
}
});
});
$socket->listen(16555, '127.0.0.1');
$loop->run();
If client is connected via telnet 'close' will be emitted so I can remove closed connection from $connection array. However, I have problem with some devices that connect to my listener too. If I turn off device 'close' will not be emitted. I tried to solve problem with periodical timer:
$loop->addPeriodicTimer(10, function () use($db, $loop){
global $connections;
foreach($connections as $c) {
$remoteAddress = $c->getRemoteAddress();
$metaData = @stream_get_meta_data($c->stream);
if(!$metaData) {
if(($key = array_search($c, $connections, true)) !== FALSE) {
unset($connections[$key]);
}
}
}
});
But seems that it is not reliable enough. Function stream_get_meta_data returns valid metadata array even though client is disconnected.