閉塞を避けるために、接続プロセスを制御するために次の方法を使用できます。
PHPのソケットはデフォルトでブロッキングモードになります。つまり、接続が成功またはタイミングが出るまで接続を待っている間にプログラムが失速します。非ブロッキングモードを設定することにより、このブロッキング動作を回避できます。
socket_set_block($socket); // ブロッキングモードに設定します
socket_set_nonblock($socket); // 非ブロッキングモードに設定します
非ブロッキングモードでは、リモートホストからの応答を待つことなく、接続要求はすぐに戻ります。したがって、プログラムは他のタスクを引き続き実行できます。接続が成功または失敗するまで、 socket_selectを介して接続のステータスを監視できます。
$timeout = 5; // タイムアウトを設定します
$start_time = time();
while (true) {
if (time() - $start_time > $timeout) {
echo "接続タイムアウト\n";
break;
}
$result = socket_addrinfo_connect($socket, $address, $port);
if ($result) {
echo "接続に正常に\n";
break;
}
// 待ってからもう一度やり直してください
usleep(100000);
}
複数のソケット接続を同時に処理する必要がある場合は、 socket_selectを使用して複数のソケットのステータスを監視できます。これにより、ループ内の複数の接続を検出でき、各接続でのブロック問題を回避できます。
$read = array($socket);
$write = null;
$except = null;
$timeout = 5; // タイムアウト設定
// 使用 socket_select タイムアウトとブロッキングの検出
$changed_sockets = socket_select($read, $write, $except, $timeout);
if ($changed_sockets === false) {
echo "socket_select エラーが発生しました\n";
} elseif ($changed_sockets > 0) {
// 如果接続に正常に,プロセス接続
echo "接続に正常に\n";
} else {
echo "接続タイムアウト\n";
}
Socket_Selectを使用すると、接続が非ブロッキングモードで成功しているかどうかを確認でき、従来のブロッキング接続プロセスを回避できます。
socket_addrinfo_connectを直接使用することに加えて、PHPはStream_Socket_Client関数も提供してソケット接続を作成および管理します。 Stream_Socket_Clientは、より高度な機能をサポートし、タイムアウトモードと非ブロッキングモードを簡単に設定できます。
$address = 'tcp://m66.net:80';
$timeout = 5; // タイムアウトを設定します
$context = stream_context_create(['socket' => ['timeout' => $timeout]]);
$socket = stream_socket_client($address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context);
if ($socket === false) {
echo "接続に失敗しました: $errstr ($errno)\n";
} else {
echo "接続に正常に\n";
fclose($socket);
}
Stream_Socket_Clientは、非ブロッキング接続をサポートするだけでなく、 Timeoutパラメーターを介して接続タイムアウトを簡単に設定して、長期ブロッキングを回避できます。
socket_addrinfo_connectまたはstream_socket_clientを使用するかどうかにかかわらず、適切な接続タイムアウトを設定することが非常に重要です。リモートホストが長い間反応しない場合、プログラムは長い間待ちます。これを防ぐために、合理的なタイムアウトメカニズムを設定することは非常に重要です。
socket_addrinfo_connectを使用する場合、接続の進行状況を監視してタイムアウトを設定することで、長いブロックを避けることができます。
$timeout = 5; // タイムアウトはです52番
$start_time = time();
while (time() - $start_time < $timeout) {
$result = socket_addrinfo_connect($socket, $address, $port);
if ($result) {
echo "接続に正常に\n";
break;
}
usleep(100000); // もう一度試す前にしばらく待ちます
}
接続時間がプリセットタイムアウト時間を超えると、プログラムは接続を積極的に中断して、無限の待機状態に陥らないようにします。