socket_set_block函數的主要功能是將一個socket 設置為阻塞模式。阻塞模式意味著,當你執行諸如socket_read或socket_write這類操作時,如果數據尚未準備好,程序將暫停等待,直到數據可用或操作完成。
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, "gitbox.net", 80);
socket_set_block($socket);
socket_write($socket, "GET / HTTP/1.1\r\nHost: gitbox.net\r\nConnection: Close\r\n\r\n");
$response = '';
while ($out = socket_read($socket, 2048)) {
$response .= $out;
}
socket_close($socket);
echo $response;
?>
在上述代碼中, socket_set_block確保了socket_read會等待數據的到來,不會立即返回。
阻塞模式的優點<br> 當程序在阻塞調用時,CPU 會被釋放給操作系統執行其他任務換句話說,CPU 不會忙於輪詢socket 狀態,而是進入休眠,等待操作系統通知數據可用。這使得CPU 使用率較低,資源得到合理利用。
阻塞模式的缺點<br> 阻塞意味著程序會停在某個調用點,如果網絡或對端響應緩慢,程序也會被“卡住”,無法處理其他任務在高並發場景下,如果使用阻塞模式的多個socket,可能導致應用響應緩慢。
雖然阻塞模式天然有助於降低CPU 佔用,但在實際應用中仍可能遇到CPU 佔用異常高的問題。常見原因包括:
頻繁非阻塞輪詢(busy waiting)
當開發者使用非阻塞模式或自己實現輪詢邏輯時,程序會不停調用讀取函數,造成CPU 一直處於忙碌狀態。
錯誤的阻塞/非阻塞模式切換<br> 如果socket 狀態切換頻繁且未合理控制,可能導致系統調用效率低下,增加CPU 負載
缺少事件驅動或異步機制<br> 僅用阻塞方式處理大量socket,導致程序無法並行處理多個連接
socket_select可以監聽多個socket 狀態,當其中一個或多個socket 可讀可寫時才進行操作,避免忙等。
<?php
$read = [$socket];
$write = $except = null;
if (socket_select($read, $write, $except, 5) > 0) {
foreach ($read as $readableSocket) {
$data = socket_read($readableSocket, 2048);
// 處理數據
}
}
?>
這樣,程序只有在socket 有數據時才會被喚醒,減少CPU 空轉。
阻塞模式下,可通過socket_set_option設置超時,防止長時間阻塞:
<?php
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ["sec"=>3, "usec"=>0]);
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, ["sec"=>3, "usec"=>0]);
?>
適當調節緩衝區大小也可以減少系統調用次數和上下文切換。
對於高並發應用,可通過多進程或多線程來分擔阻塞帶來的瓶頸,避免單進程阻塞影響整體性能。
PHP 有諸如Swoole 、 ReactPHP等異步擴展,支持非阻塞和事件驅動模型,極大提高資源利用率,降低CPU 佔用。
socket_set_block讓socket 操作阻塞,減少CPU 空轉,提高單連接的效率。
阻塞模式在高並發場景下可能導致應用響應緩慢。
結合socket_select等多路復用技術,合理設置超時參數,可以顯著降低CPU 佔用。
採用異步或多進程模型是提升性能和資源利用的有效手段。
理解socket_set_block對CPU 影響的原理,並配合合理優化,能讓PHP 網絡應用更加高效穩定。