当前位置: 首页> 最新文章列表> 在 socket_connect 之后使用 socket_set_block 的正确姿势

在 socket_connect 之后使用 socket_set_block 的正确姿势

gitbox 2025-05-26

1. socket_connect 和阻塞模式的关系

默认情况下,PHP 中的 socket 是阻塞模式的,调用 socket_connect 会阻塞直到连接成功或失败返回。但如果你在连接后,想确保后续读写操作依然保持阻塞,可以使用 socket_set_block 来显式设置。

需要注意的是,socket_set_block 必须在 socket_connect 之后调用才能生效。因为:

  • 连接建立前设置阻塞模式可能会被 socket_connect 重置。

  • 连接后设置可以保证所有后续操作均为阻塞模式。


2. 正确调用 socket_set_block 的示例

以下是一个完整的示例,展示如何在连接成功后调用 socket_set_block

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

// 连接到服务器
$address = 'gitbox.net';
$port = 80;
if (!socket_connect($socket, $address, $port)) {
    die("socket_connect 失败: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// 连接成功后,设置阻塞模式
if (!socket_set_block($socket)) {
    die("socket_set_block 失败: " . socket_strerror(socket_last_error($socket)) . "\n");
}

// 现在 socket 是阻塞的,可以进行读写操作
$request = "GET / HTTP/1.1\r\nHost: gitbox.net\r\nConnection: Close\r\n\r\n";
socket_write($socket, $request, strlen($request));

// 读取响应
$response = '';
while ($out = socket_read($socket, 2048)) {
    $response .= $out;
}

// 关闭 socket
socket_close($socket);

// 输出响应
echo $response;
?>

3. 需要注意的点

  • 确保 socket_connect 成功后再调用 socket_set_block,避免连接失败后再设置。

  • socket_set_block 返回布尔值,失败时可以通过 socket_last_error 获取错误信息。

  • 如果你在连接前调用 socket_set_block,可能会被连接过程中的内部调用覆盖,导致阻塞设置无效。

  • PHP 的默认 socket 模式通常是阻塞,但在某些场景下(如之前调用过 socket_set_nonblock)需要重新设置回阻塞。


总结来说,想保证阻塞模式生效,关键就是在 socket_connect 成功之后调用 socket_set_block,这样可以确保后续读写操作都以阻塞方式执行,从而避免非阻塞模式下常见的读取不到数据或写入失败的问题。