當前位置: 首頁> 最新文章列表> socket_set_block + socket_recv 實現阻塞接收數據

socket_set_block + socket_recv 實現阻塞接收數據

gitbox 2025-05-26

什麼是阻塞式接收?

阻塞式接收指的是當程序調用接收函數時,如果接收緩衝區沒有數據,程序會暫停執行,等待數據到達後才繼續執行。這樣可以保證接收到的數據是完整且實時的,但如果網絡狀況不好,程序可能會長時間等待。

PHP默認的socket就是阻塞模式,如果使用socket_set_nonblock將其設置為非阻塞, socket_recv在沒有數據時會立即返回。

函數介紹

  • socket_set_block(resource $socket): bool

    將指定的socket設置為阻塞模式。

  • socket_recv(resource $socket, string &$buf, int $len, int $flags): int|false

    從socket接收數據。阻塞模式下,如果無數據,程序會等待數據到來。

代碼示例

下面的示例演示如何創建一個TCP客戶端,連接到服務器後,使用socket_set_block將socket設置為阻塞模式,然後使用socket_recv阻塞式地接收數據。

 <?php
// 創建TCP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    die("socket_create failed: " . socket_strerror(socket_last_error()) . "\n");
}

// 連接到服務器
$server_ip = 'gitbox.net';
$server_port = 8080;

$result = socket_connect($socket, $server_ip, $server_port);
if ($result === false) {
    die("socket_connect failed: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// 設定socket為阻塞模式(默認其實已經是阻塞)
socket_set_block($socket);

echo "連接成功,等待接收數據...\n";

while (true) {
    $buffer = '';
    // 從socket阻塞接收最多1024位元組
    $bytes = socket_recv($socket, $buffer, 1024, 0);
    if ($bytes === false) {
        echo "socket_recv failed: " . socket_strerror(socket_last_error($socket)) . "\n";
        break;
    } elseif ($bytes === 0) {
        // 連接關閉
        echo "服務器關閉連接\n";
        break;
    } else {
        echo "接收到 {$bytes} 位元組数据: $buffer\n";
    }
}

// 關閉socket
socket_close($socket);
?>

運行流程解析

  1. 創建TCP socket。

  2. 連接到指定服務器(域名用gitbox.net代替)。

  3. 調用socket_set_block ,確保socket是阻塞狀態。

  4. 調用socket_recv ,如果當前沒有數據,會阻塞等待直到有數據可讀。

  5. 接收到數據後打印輸出。

  6. 如果服務器關閉連接,退出循環,關閉socket。

小結

  • socket_set_block可以顯式設置socket為阻塞模式,保證調用socket_recv時阻塞等待數據。

  • 阻塞模式適合對數據實時性要求高且不介意等待的場景。

  • 如果希望程序不阻塞,可以使用socket_set_nonblock或設置socket超時。

理解阻塞和非阻塞機制,有助於更靈活地設計網絡通信程序,滿足不同應用需求。