我来分析一下为什么 RPC 服务端的 receive 事件没有收到数据。通过查看代码,我发现了几个关键问题:
在 RpcClient.php 中,数据发送使用了 JsonProtocol::encode() 进行编码,它会在 JSON 数据后添加换行符 "\n" 作为结束标记。
在 RpcService.php 中,服务端配置了固定包头协议(代码被注释掉了),但实际处理时没有使用任何协议解析。
在 RpcService.php 中,receive 事件处理器直接接收原始数据,没有处理可能的粘包问题。
解决方案:
首先需要取消注释并配置服务端的协议设置:
代码位置:RpcService.php
修改为:
// 设置 RPC 端口的独立参数(使用换行符作为分包协议)
$rpcPort->set([
'open_eof_check' => true,
'package_eof' => "\n",
'open_eof_split' => true,
]);
修改 receive 事件处理逻辑,添加数据验证:
代码位置:RpcService.php
修改为:
$rpcPort->on('receive', function (SwooleServer $serv, int $fd, int $reactorId, string $data)
{
if (empty($data)) {
return;
}
file_put_contents(runtime_path() . '/rpc.log', date('Y-m-d H:i:s') . " Received: " . $data . "\n", FILE_APPEND);
$this->handleRpcRequest($serv, $fd, $reactorId, $data);
});
在 handleRpcRequest 方法中添加更详细的日志记录:
代码位置:RpcService.php
修改为:
protected function handleRpcRequest(SwooleServer $serv, int $fd, $reactorId, string $data)
{
try {
// 记录接收到的原始数据
file_put_contents(runtime_path() . '/rpc.log', date('Y-m-d H:i:s') . " Processing: " . $data . "\n", FILE_APPEND);
// 去掉换行符
$data = trim($data);
// 解析 JSON 数据
$request = json_decode($data, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Exception("Invalid JSON data: " . json_last_error_msg());
}
确保响应数据也添加换行符:
代码位置:RpcService.php
修改为:
// 响应客户端(添加换行符作为结束标记)
$sendData = json_encode($response) . "\n";
return $serv->send($fd, $sendData, $reactorId);
这些修改的主要目的是:
配置 Swoole 使用换行符作为分包协议,确保正确处理数据包边界
添加数据验证和错误处理
增加详细的日志记录,便于调试
确保服务端和客户端使用相同的协议格式
修改后,请检查 runtime_path() . '/rpc.log' 文件,查看是否有数据接收记录。如果仍然没有数据,可能需要检查:
客户端连接的地址和端口是否正确
防火墙是否阻止了连接
Swoole 服务是否正常启动并监听在指定端口