PHP socket_set_blocking 函数
最后修改于 2025 年 4 月 4 日
PHP 的 socket_set_blocking 函数用于控制套接字的阻塞模式。它决定了套接字操作是否会等待完成。
基本定义
socket_set_blocking 将套接字设置为阻塞或非阻塞模式。在阻塞模式下,操作会一直等待直到可以完成。
语法:socket_set_blocking(Socket $socket, bool $enable): bool。成功时返回 true,失败时返回 false。会影响所有后续操作。
基本阻塞套接字示例
本示例演示了为简单的 TCP 客户端创建一个阻塞套接字。
blocking_socket.php
<?php
declare(strict_types=1);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("Socket creation failed");
}
// Set socket to blocking mode
socket_set_blocking($socket, true);
$connected = socket_connect($socket, 'example.com', 80);
if ($connected === false) {
die("Connection failed");
}
echo "Connected in blocking mode\n";
socket_close($socket);
这会创建一个阻塞模式的 TCP 套接字。connect 操作将一直等待直到成功或失败。对于基本操作,阻塞模式更简单。
非阻塞套接字示例
这展示了如何为异步操作创建非阻塞套接字。
non_blocking_socket.php
<?php
declare(strict_types=1);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("Socket creation failed");
}
// Set socket to non-blocking mode
socket_set_blocking($socket, false);
$connected = socket_connect($socket, 'example.com', 80);
if ($connected === false) {
$error = socket_last_error($socket);
if ($error !== SOCKET_EINPROGRESS) {
die("Connection failed");
}
echo "Connection in progress\n";
}
socket_close($socket);
非阻塞模式会立即返回。代码必须处理 EINPROGRESS 错误。这允许进行异步网络编程。
模式切换
本示例演示了在阻塞模式之间动态切换。
mode_switching.php
<?php
declare(strict_types=1);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, 'example.com', 80);
// Start in blocking mode for initial data
socket_set_blocking($socket, true);
$data = socket_read($socket, 1024);
// Switch to non-blocking for subsequent reads
socket_set_blocking($socket, false);
while (true) {
$more = socket_read($socket, 1024);
if ($more === false) break;
$data .= $more;
}
echo "Received data: " . strlen($data) . " bytes\n";
socket_close($socket);
这在初始数据使用阻塞模式,然后切换到非阻塞模式。这种方法结合了两种模式以实现灵活的网络通信。
阻塞套接字的超时处理
本示例展示了如何使用阻塞套接字实现超时。
timeout_handling.php
<?php
declare(strict_types=1);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_blocking($socket, true);
// Set timeout options
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, [
"sec" => 5,
"usec" => 0
]);
$connected = socket_connect($socket, 'example.com', 80);
if ($connected === false) {
die("Connection failed");
}
$data = socket_read($socket, 1024);
if ($data === false) {
die("Read timed out after 5 seconds");
}
echo "Received data: $data\n";
socket_close($socket);
即使在阻塞模式下,也可以使用套接字选项设置超时。这可以防止无限等待,同时保持阻塞模式的简单性。
非阻塞套接字服务器
本示例创建了一个简单的非阻塞套接字服务器。
non_blocking_server.php
<?php
declare(strict_types=1);
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($server, '0.0.0.0', 8080);
socket_listen($server);
// Set server socket to non-blocking
socket_set_blocking($server, false);
echo "Server running on port 8080 (non-blocking)\n";
while (true) {
$client = socket_accept($server);
if ($client === false) {
usleep(100000); // Sleep to prevent CPU overload
continue;
}
$data = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, World!";
socket_write($client, $data);
socket_close($client);
}
非阻塞服务器在不等待的情况下检查连接。当没有可用连接时,它会短暂休眠以减少 CPU 使用率。
最佳实践
- 错误处理:始终检查套接字操作的返回值。
- 资源管理:完成后正确关闭套接字。
- 性能:高并发服务器请使用非阻塞模式。
- 简单性:简单客户端请优先使用阻塞模式。
- 超时:为阻塞操作设置适当的超时。
来源
本教程通过针对不同网络编程场景的实际示例,介绍了 PHP socket_set_blocking 函数。
作者
列出 所有 PHP 网络函数。