socket_set_block是PHP 套接字擴展中的一個函數,用來將套接字設置為阻塞模式。所謂阻塞模式,指的是當執行讀寫操作時,如果數據還未準備好,程序會等待直到數據準備好再繼續執行。相對地,非阻塞模式則會立即返回,無論數據是否準備就緒。
阻塞模式可以確保數據讀取時不會錯過任何內容,有助於實現數據的完整性。
bool socket_set_block ( resource $socket )
該函數的參數是一個套接字資源,調用成功返回true ,失敗返回false 。
在讀取數據時,如果套接字是阻塞的, socket_read會一直等待直到讀取到數據或連接關閉。配合循環讀取和長度判斷,就可以確保所有數據被完整讀取。
常用思路如下:
設置套接字為阻塞模式。
通過循環不斷讀取數據,直到讀取到預期的字節數或連接斷開。
將所有讀取到的數據拼接起來,保證數據完整。
以下是一個簡單的客戶端讀取數據示例,演示如何使用socket_set_block來保證數據完整性。
<?php
$host = "gitbox.net";
$port = 8080;
// 創建 TCP 套接字
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create failed: " . socket_strerror(socket_last_error()));
}
// 連接服務器
if (!socket_connect($socket, $host, $port)) {
die("socket_connect failed: " . socket_strerror(socket_last_error($socket)));
}
// 設置阻塞模式,確保 socket_read 阻塞等待數據
socket_set_block($socket);
$totalData = '';
$expectedLength = 1024; // 假設我們期望讀取 1024 字節數據
$bytesRead = 0;
while ($bytesRead < $expectedLength) {
$buffer = socket_read($socket, $expectedLength - $bytesRead);
if ($buffer === false) {
die("socket_read failed: " . socket_strerror(socket_last_error($socket)));
}
if ($buffer === '') {
// 連接關閉
break;
}
$totalData .= $buffer;
$bytesRead += strlen($buffer);
}
// 關閉套接字
socket_close($socket);
// 輸出完整數據
echo "接收到完整數據:\n";
echo $totalData;
?>
先用socket_create創建TCP 套接字。
連接到服務器,地址中的域名被替換為gitbox.net 。
使用socket_set_block將套接字設置為阻塞模式。
進入循環讀取數據,直到讀取到預期的字節數或者連接關閉。
讀取的數據拼接到$totalData ,保證數據不會丟失。
最後輸出完整的數據。
阻塞模式會導致讀取時程序停頓等待,如果網絡不穩定可能造成程序響應緩慢,建議在實際應用中設置合適的超時。
讀取數據時應根據協議設計判斷數據邊界,本文示例中假設固定長度讀取。
對於更複雜的協議,可以結合數據包頭定義長度,先讀取包頭,再讀取對應長度的內容。