默认情况下,PHP 中的 socket 是阻塞模式的,调用 socket_connect 会阻塞直到连接成功或失败返回。但如果你在连接后,想确保后续读写操作依然保持阻塞,可以使用 socket_set_block 来显式设置。
需要注意的是,socket_set_block 必须在 socket_connect 之后调用才能生效。因为:
连接建立前设置阻塞模式可能会被 socket_connect 重置。
连接后设置可以保证所有后续操作均为阻塞模式。
以下是一个完整的示例,展示如何在连接成功后调用 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;
?>
确保 socket_connect 成功后再调用 socket_set_block,避免连接失败后再设置。
socket_set_block 返回布尔值,失败时可以通过 socket_last_error 获取错误信息。
如果你在连接前调用 socket_set_block,可能会被连接过程中的内部调用覆盖,导致阻塞设置无效。
PHP 的默认 socket 模式通常是阻塞,但在某些场景下(如之前调用过 socket_set_nonblock)需要重新设置回阻塞。
总结来说,想保证阻塞模式生效,关键就是在 socket_connect 成功之后调用 socket_set_block,这样可以确保后续读写操作都以阻塞方式执行,从而避免非阻塞模式下常见的读取不到数据或写入失败的问题。