You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP中完整读取Unix域Socket的fread输出?

解决Unix域Socket读取内容截断问题

原代码的核心问题是:当Socket发送端未关闭连接,且当前缓冲区数据被读完后,fread()会返回空字符串,导致循环提前终止,而此时服务器可能还在发送剩余的JSON数据。

以下是两种可行的修改方案:

方案一:基于结束标记+超时读取

通过检测JSON的结束符}来判断是否读取完成,同时设置读取超时避免无限等待:

<?php
$socket = '/var/run/qemu-server/121.serial1';
$sock = stream_socket_client('unix://'.$socket, $errno, $errstr, 30);
if (!$sock) {
    die("连接失败: $errstr ($errno)");
}

// 设置5秒读取超时,可根据实际情况调整
stream_set_timeout($sock, 5);

fwrite($sock, $argv[1] . "\n");

$data = '';
$endMarker = '}';
$foundEnd = false;

while (!$foundEnd) {
    $buffer = fread($sock, 8128);
    if ($buffer === false || $buffer === '') {
        $info = stream_get_meta_data($sock);
        // 超时则退出循环
        if ($info['timed_out']) {
            break;
        }
        continue;
    }
    $data .= $buffer;
    // 检测到结束符则终止读取,截断到结束位置
    if (strpos($data, $endMarker) !== false) {
        $foundEnd = true;
        $data = substr($data, 0, strpos($data, $endMarker) + 1);
    }
}

echo $data;
fclose($sock);
?>

方案二:使用stream_select监听可读事件

通过stream_select()监听Socket的可读状态,确保只有在有数据时才读取,避免提前终止循环:

<?php
$socket = '/var/run/qemu-server/121.serial1';
$sock = stream_socket_client('unix://'.$socket, $errno, $errstr, 30);
if (!$sock) {
    die("连接失败: $errstr ($errno)");
}

fwrite($sock, $argv[1] . "\n");

$data = '';
$read = [$sock];
$write = null;
$except = null;

// 设置10秒等待超时,可根据实际情况调整
while (stream_select($read, $write, $except, 10)) {
    $buffer = fread($sock, 8128);
    if ($buffer === false || $buffer === '') {
        break;
    }
    $data .= $buffer;
    // 检测到JSON结束符则提前退出
    if (strpos($data, '}') !== false) {
        $data = substr($data, 0, strpos($data, '}') + 1);
        break;
    }
    // 重置可读数组,因为stream_select会修改它
    $read = [$sock];
}

echo $data;
fclose($sock);
?>

关键说明

  • 如果服务器端在发送完完整数据后会主动关闭Socket连接,原代码本应正常工作,但显然你的场景中服务器未关闭连接,因此需要主动判断结束条件。
  • 超时时间需要根据实际业务场景调整,确保服务器有足够时间发送完整数据。

内容的提问来源于stack exchange,提问作者RafaelB13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:45:58