現在の位置: ホーム> 最新記事一覧> プログラムの長期ブロッキングを回避するために、stream_socket_recvfrom関数で読み取りタイムアウトを設定する方法は?

プログラムの長期ブロッキングを回避するために、stream_socket_recvfrom関数で読み取りタイムアウトを設定する方法は?

M66 2025-06-22

ネットワークプログラミングにPHPを使用する場合、 Stream_Socket_RecvFrom関数は、UDPパケットを受信するために一般的に使用される関数です。ただし、デフォルトでは、この関数はデータが受信されるか、エラーが発生するまでデータを待機している間にブロックされます。シナリオでは、プログラムに長期的な一時停止を引き起こし、パフォーマンスとユーザーエクスペリエンスに影響します。この長いブロッキングを避けるために、読み取りタイムアウトを設定する必要があります。

この記事では、 Stream_Socket_RecvFrom関数で読み取りタイムアウトを設定する方法を詳細に説明し、プログラムの動作をよりよく制御するのに役立ちます。


1。stream_socket_recvfrom紹介

stream_socket_recvfrom関数の基本的な使用法は次のとおりです。

 $data = stream_socket_recvfrom($socket, 1024);

指定された$ソケットから最大1024バイトのデータを読み取ります。データが届かない場合、関数はブロックして待機します。


2。問題のブロックとタイムアウト設定の必要性

Stream_Socket_recvfromが呼び出されると、ピアが長い間データを送信しない場合、プログラムは待機します。これは、ネットワークアプリケーションの応答速度と安定性に非常に不利です。プログラムが長い間立ち往生しているのを避けるために、タイムアウトメカニズムを設定する必要があり、タイムアウトがタイムアウトしたら、読み取りをあきらめて他の処理を実行します。


3.読み取りタイムアウトを設定する方法

PHPでは、通常、操作ストリームタイムアウトは、 stream_set_timeout関数を介して実装されます。この関数は、オープンストリームのタイムアウト時間を設定できます。

例:

 // 作成する UDP socket
$socket = stream_socket_server("udp://0.0.0.0:9999", $errno, $errstr, STREAM_SERVER_BIND);

if (!$socket) {
    die("无法作成するsocket: $errstr ($errno)\n");
}

// タイムアウトを設定します,2番単位とマイクロ2番単位
// 这里タイムアウトを設定します时间为 5 2番
stream_set_timeout($socket, 5);

// 読み取り関数を呼び出します
$data = stream_socket_recvfrom($socket, 1024);

$info = stream_get_meta_data($socket);
if ($info['timed_out']) {
    echo "データのタイムアウトを読んでください,待っているのをあきらめる\n";
} else {
    echo "受信したデータ: $data\n";
}
  • stream_set_timeout($ socket、5)は、 5秒のタイムアウトを設定します。

  • データを読んだ後、Timeoutがstream_get_meta_data($ socket)によって達成されるかどうかを判断します。


4.ポーリングと組み合わせて非ブロッキングモードを使用します

タイムアウトメカニズムに加えて、もう1つの一般的な実践は、ソケットを非ブロッキングモードに設定し、ポーリングまたはイベント駆動型メカニズムと併せてデータを読み取ることです。

 // 作成する socket
$socket = stream_socket_server("udp://0.0.0.0:9999", $errno, $errstr, STREAM_SERVER_BIND);

if (!$socket) {
    die("无法作成するsocket: $errstr ($errno)\n");
}

// 非ブロッキングモードを設定します
stream_set_blocking($socket, false);

$startTime = time();
$timeout = 5; // 2番

while (true) {
    $data = stream_socket_recvfrom($socket, 1024);
    if ($data !== false && $data !== '') {
        echo "受信したデータ: $data\n";
        break;
    }
    
    if (time() - $startTime > $timeout) {
        echo "タイムアウトを読んでください,ループを終了します\n";
        break;
    }
    
    // 避けるCPU占有が高すぎる,適切に眠ります
    usleep(100000); // 100毫2番
}

この方法により、読み取りロジックのより柔軟な制御が可能になり、イベントループの統合が容易になります。


5。概要

  • stream_socket_recvfromデフォルトでブロックされます。これにより、プログラムが長い間待つことがあります。

  • Stream_set_timeoutを使用して、タイムアウト時間を設定して、ブロッキングが長すぎないようにします。

  • 読んだ後、 Stream_get_meta_dataを使用して、タイムアウトに到達するかどうかを判断します。

  • 非ブロッキングモードを使用して、ポーリングで読み取り時間を制御することもできます。

タイムアウトパラメーターを合理的に設定することは、ネットワークプログラムの安定した応答を確保するための鍵です。