現在の位置: ホーム> 最新記事一覧> socket_clear_error()を介して長い接続を維持する方法は?

socket_clear_error()を介して長い接続を維持する方法は?

M66 2025-06-12

PHPを使用してソケットベースのサーバーまたはクライアントプログラムを構築する場合、永続的な接続は非常に一般的な要件です。特に、インスタントメッセージング、オンラインゲームサーバー、データプッシュなどのシナリオでは、ソケットを長時間接続し、常に並べることは、パフォーマンスとユーザーエクスペリエンスに大きな影響を与えます。

このシナリオでは、 socket_clear_error()の合理的な使用は、接続を安定させるための重要な手段です。この記事では、それがどのように使用されるかを詳細に調べ、いくつかの実用的な例を組み合わせて、不明確なエラーによる接続の中断を避ける方法を説明します。


1。socket_clear_error()とは

socket_clear_error()は、指定されたソケットに関連付けられたエラー情報をクリアするためにPHPによって提供されるソケット操作機能です。関数の署名は次のとおりです。

 void socket_clear_error ([ resource $socket ] )

特定のソケットまたはグローバルで使用できます。ソケット操作でエラーが発生すると、エラーメッセージが保存されます。これらのエラーが時間内にクリアされていない場合、次にソケット機能が呼び出されたときに動作に影響し、接続が切断される可能性があります。


2。なぜワイヤーが切断されるのですか?

次のような長い接続を使用する場合、切断には多くの理由があります。

  • ネットワークジッター;

  • クライアントは接続を閉じます。

  • サーバー内部処理エラーはキャッチされていません。

  • エラースタッキングはクリアされていません。

最後のものは、私たちの記事の焦点です。わずかな非脂肪エラーであっても、 socket_clear_error()を介してクリアされていない場合、 socket_write()socket_read()などの次回は異常に戻るか、「エラー状態」が検出されたために割り込みをトリガーする場合があります。


3。例分析:接続を維持するためのヒント

以下は、クライアントのリクエストを処理し、長い接続を維持する典型的なPHPソケットサーバー側のコードスニペットです。

 $host = '0.0.0.0';
$port = 9000;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket);

$clients = [];

while (true) {
    $read = $clients;
    $read[] = $socket;

    $write = $except = null;
    socket_select($read, $write, $except, 0, 200000); // ノンブロッキング

    if (in_array($socket, $read)) {
        $client = socket_accept($socket);
        $clients[] = $client;
        socket_clear_error($client); // 新しい接続のエラーステータスをクリアします
    }

    foreach ($clients as $key => $client) {
        $data = @socket_read($client, 1024, PHP_NORMAL_READ);
        if ($data === false) {
            $error = socket_last_error($client);
            if ($error !== 0) {
                echo "Socket error: " . socket_strerror($error) . "\n";
                socket_clear_error($client);
            }
            continue;
        }

        $data = trim($data);
        if ($data == 'quit') {
            socket_close($client);
            unset($clients[$key]);
            continue;
        }

        $response = "Server received: $data\n";
        @socket_write($client, $response, strlen($response));
        socket_clear_error($client); // 各通信後のクリアエラー
    }
}

このコードは、いくつかの重要な戦略を示しています。

  • クライアント接続を受信するたびに、 socket_clear_error()を使用してステータスをすぐにクリアします。

  • 読み取りまたは書き込み操作のたびに可能なエラーをクリアします。

  • 非脂肪のエラー(一時的なネットワークの停止など)の場合、すぐに切断するのではなく、処理をクリアして継続してみてください。


4.ハートビートメカニズムを使用して、接続メンテナンスを最適化します

クリアのエラーに加えて、「ハートビートパッケージ」を合理的に設計することも、接続を常に維持するための鍵です。ハートビートメカニズムにより、クライアントは固定時間に軽量データパケットをサーバーに送信できます。一定期間後にハートビートが受信されない場合、接続を自動的に閉じることができます。

 // ハートビート応答の例の簡素化されたバージョン
if ($data == 'ping') {
    @socket_write($client, "pong\n");
    socket_clear_error($client);
}

これにより、socket_clear_error()を使用した「実際の壊れた線」と「誤差線」の違いをよりよく検出できます。


5.ゾンビ接続と例外状態を処理します

エラーを長時間クリアしないと、いわゆる「ゾンビ接続」が発生します。つまり、ソケットオブジェクトはまだ存在しますが、すでに無効な状態です。すべてのクライアントのステータスを定期的に確認する方法は次のとおりです。