当前位置: 首页> 最新文章列表> 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超时。

理解阻塞和非阻塞机制,有助于更灵活地设计网络通信程序,满足不同应用需求。