TCPリスナーコンポーネントにReactPHPを使用しています。このコンポーネントは、着信接続をリッスンし、それらとデータを交換します。$connections 配列は、クライアントがリスナーに接続/切断すると更新されます。
$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();
クライアントが telnet 経由で接続されている場合、'close' が出力されるため、閉じた接続を $connection 配列から削除できます。ただし、リスナーに接続する一部のデバイスにも問題があります。デバイスをオフにすると、「閉じる」は出力されません。定期的なタイマーの問題を解決しようとしました:
$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]);
}
}
}
});
しかし、それは十分に信頼できないようです。関数 stream_get_meta_data は、クライアントが切断されていても有効なメタデータ配列を返します。