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,保证数据不会丢失。
最后输出完整的数据。
阻塞模式会导致读取时程序停顿等待,如果网络不稳定可能造成程序响应缓慢,建议在实际应用中设置合适的超时。
读取数据时应根据协议设计判断数据边界,本文示例中假设固定长度读取。
对于更复杂的协议,可以结合数据包头定义长度,先读取包头,再读取对应长度的内容。