現在の位置: ホーム> 最新記事一覧> Networkアプリケーションのパフォーマンスを改善するために、Stream_set_blockingを介してPHPでのソケットの読み取り動作を制御する方法は?

Networkアプリケーションのパフォーマンスを改善するために、Stream_set_blockingを介してPHPでのソケットの読み取り動作を制御する方法は?

gitbox 2025-09-20
<span><span><span class="hljs-meta">&lt;?php</span></span><span>
</span><span><span class="hljs-comment">// 次のコンテンツは、記事のメインテキストとは何の関係もありません</span></span><span>
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"これが例です PHP コード,記事に関係のない序文を表示するために使用されます。\n"</span></span><span>;

-------------------------------------------------------------------------------

<span class="hljs-comment">/**
 * 合格する方法 stream_set_blocking コントロール PHP ソケットの読み取り行動,ネットワークアプリケーションのパフォーマンスを改善します?
 *
 * 存在する PHP ネットワークプログラミングで,ソケット(socket)読み取り動作は、アプリケーションのパフォーマンスに直接影響を与えます。デフォルトで,
 * PHP 的ソケット操作是阻塞式的,つまり、読み取り関数を呼び出すときです(のように fread または stream_get_contents)時間,
 * のように果没有数据到达,プログラムは待ちます,データが利用可能になるまで。这种行为存在する高并发または长连接场景下容易导致性能瓶颈。
 *
 * この問題を解決するために,PHP 提供された stream_set_blocking 関数,可以灵活地コントロールソケット的ブロッキングモード。
 *
 * 1つ、stream_set_blocking 基本的な使用法
 *
 * 関数原型:
 * bool stream_set_blocking ( resource $stream , int $mode )
 *
 * パラメーターの説明:
 * - $stream: ソケットリソース(stream リソース)。
 * - $mode: ブロッキングモード,1 ブロッキングを示します(blocking),0 非ブロッキングを示します(non-blocking)。
 *
 * 例:
 */</span>
</span><span><span class="hljs-variable">$socket</span></span><span> = </span><span><span class="hljs-title function_ invoke__">stream_socket_client</span></span><span>(</span><span><span class="hljs-string">"tcp://127.0.0.1:8080"</span></span><span>, </span><span><span class="hljs-variable">$errno</span></span><span>, </span><span><span class="hljs-variable">$errstr</span></span><span>, </span><span><span class="hljs-number">30</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (!</span><span><span class="hljs-variable">$socket</span></span><span>) {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"接続に失敗しました: <span class="hljs-subst">$errstr</span></span></span><span> (</span><span><span class="hljs-subst">$errno</span></span><span>)\n";
} </span><span><span class="hljs-keyword">else</span></span><span> {
    </span><span><span class="hljs-comment">// 设置非ブロッキングモード</span></span><span>
    </span><span><span class="hljs-title function_ invoke__">stream_set_blocking</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>, </span><span><span class="hljs-number">0</span></span><span>);
    
    </span><span><span class="hljs-comment">// データを読んでみてください</span></span><span>
    </span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fread</span></span><span>(</span><span><span class="hljs-variable">$socket</span></span><span>, </span><span><span class="hljs-number">8192</span></span><span>);
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$data</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
        </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"現在、読みやすいデータはありません,プログラムは引き続き実行されます。\n"</span></span><span>;
    } </span><span><span class="hljs-keyword">else</span></span><span> {
        </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"データを読む: <span class="hljs-subst">$data</span></span></span><span>\n";
    }
}
-------------------------------------------------------------------------------

<span class="hljs-comment">/**
 * 二、ブロッキングモード与非ブロッキングモード的差异
 *
 * 1. ブロッキングモード(blocking)
 *    - fread または fgets 戻る前にデータが到着するのを待ちます。
 *    - 単一のスレッドに適しています、低い並行シナリオ。
 *    - 単純,但可能导致长時間间等待阻塞整个脚本。
 *
 * 2. 非ブロッキングモード(non-blocking)
 *    - fread 等関数立即返回,若无数据则返回空または false。
 *    - 非同期処理に適しています、高い並行性シナリオ。
 *    - 組み合わせることができます stream_select 监控多个ソケット的可读状态,これにより、ネットワークアプリケーションのパフォーマンスが向上します。
 *
 * 三つ、組み合わせた stream_select パフォーマンスを向上させます
 *
 * stream_select 複数のストリームが読みやすいかどうかを監視できます、可写または发生异常:
 *
 * 例:
 */</span>
</span><span><span class="hljs-variable">$read</span></span><span> = [</span><span><span class="hljs-variable">$socket</span></span><span>];
</span><span><span class="hljs-variable">$write</span></span><span> = </span><span><span class="hljs-literal">null</span></span><span>;
</span><span><span class="hljs-variable">$except</span></span><span> = </span><span><span class="hljs-literal">null</span></span><span>;
</span><span><span class="hljs-variable">$timeout</span></span><span> = </span><span><span class="hljs-number">2</span></span><span>; </span><span><span class="hljs-comment">// 超時間時間间 2 2番</span></span><span>

</span><span><span class="hljs-variable">$num_changed_streams</span></span><span> = </span><span><span class="hljs-title function_ invoke__">stream_select</span></span><span>(</span><span><span class="hljs-variable">$read</span></span><span>, </span><span><span class="hljs-variable">$write</span></span><span>, </span><span><span class="hljs-variable">$except</span></span><span>, </span><span><span class="hljs-variable">$timeout</span></span><span>);
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$num_changed_streams</span></span><span> === </span><span><span class="hljs-literal">false</span></span><span>) {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"监控ソケット出错\n"</span></span><span>;
} </span><span><span class="hljs-keyword">elseif</span></span><span> (</span><span><span class="hljs-variable">$num_changed_streams</span></span><span> === </span><span><span class="hljs-number">0</span></span><span>) {
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"超時間,まだ読みやすいデータはありません\n"</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
    </span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$read</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$r</span></span><span>) {
        </span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fread</span></span><span>(</span><span><span class="hljs-variable">$r</span></span><span>, </span><span><span class="hljs-number">8192</span></span><span>);
        </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"受信したデータ: <span class="hljs-subst">$data</span></span></span><span>\n";
    }
}
-------------------------------------------------------------------------------

<span class="hljs-comment">/**
 * 4、実用的なアプリケーションでのパフォーマンス最適化の提案
 *
 * 1. 存在する高并发网络应用中,尽量使用非ブロッキングモード读取ソケット,プロセス全体を単一の遅い接続でブロックしないでください。
 * 2. 使用 stream_select または类似事件循环机制(のように ReactPHP)来轮询多个ソケット。
 * 3. 長いつながりのために,合理设置读取超時間時間间,無限の詰まりを避けてください。
 * 4. 避免存在するブロッキングモード下处理大量数据,必要時間可分块读取または使用缓冲。
 *
 * 合理的な使用によって stream_set_blocking イベントループメカニズム,大幅に改善できます PHP ネットワークアプリケーションの応答速度とスループット。
 */</span>
</span><span><span class="hljs-meta">?&gt;</span></span><span>
</span></span>