workerman中解包出现错误导致socket被关闭,但代码并没有执行解包操作,如何排除

环境

  1. php 7.2.19
  2. workerman 3.5
  3. protobuf

相关代码

<?php

use Workerman\Worker;

$gateway = new Worker("protobuf://0.0.0.0:6577");
// 名称,
$gateway->name = 'imageFlow';
//进程数
$gateway->count = 4;
$gateway->reusePort = true;

$gateway->onMessage = function ($connection, $data) {
    try {
        \Applications\imageFlow\Events::onMessage($connection, $data);
    } catch(\Error $e) {
        //这里并没有捕获到错误
    }
};

$gateway->onClose = function ($connection) {
    \Applications\imageFlow\Events::onClose($connection);
};

// 如果不是在根目录启动,则运行runAll方法
if (!defined('GLOBAL_START')) {
    Worker::runAll();
}

protobuf协议代码

<?php

namespace Protocols;

use Workerman\Connection\TcpConnection;

class Protobuf
{

    /**
     * Check the integrity of the package.
     *
     * @param string $buffer
     * @param TcpConnection $connection
     * @return int
     */
    public static function input($buffer, TcpConnection $connection)
    {
    }

    /**
     * Decode.
     *
     * @param string $buffer
     * @return array
     */
    public static function decode($buffer)
    {
        //nameLen
        $unpack_data = unpack("a*body", $buffer);
        /**
        忽略计算过程
        */

        if ($crc32 !== $calculation) {
        /*crc32计算不准确则返回error*/
            return "error";
        }


        return [
            'package_name' => $package_name,
            'data' => $data,
        ];
    }

    /**
     * Encode.
     *
     * @param array $buffer
     * @return string
     */
    public static function encode($buffer, $connection)
    {
    }
}

业务代码

<?php
namespace Applications\imageFlow;

class Events
{
    /**
     * 当客户端发来消息时触发
     * @param $connection 连接
     * @param mixed $message 具体消息
     */
    public static function onMessage($connection, $message)
    {
        try {
            if ($message == 'error') {
                /**/
                return "这里返回后就出现了socket被主动断掉得情况";
            }
            //这里执行了解包操作
        } catch (\Error $e) {
            //这里也没有捕获到错误
        }
    }

    /**
     * 当用户断开连接时触发
     * @param $connection 连接
     */
    public static function onClose($connection)
    {
    //这里执行了close
        var_dump("客户端断开:" . $connection);
    }


}

通过strace发现有error

workerman中解包出现错误导致socket被关闭,但代码并没有执行解包操作,如何排除

猜测是因为这个Error package. package_length=10....(这个应该是protobuf解包出现的错误) 导致报错,worker主动断开了socket, 但是排查代码流程里面并没有这个操作。

想问一下怎么找到strace这个报错的代码点

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

看起来是13这个fd引起的,建议strace的同时看一下这个pid对应的这个fd是什么连接,ls /proc/{$pid}/fd/{$fd}, 再考虑下一步的排查思路。

4年前 评论
sunrise丶 (楼主) 4年前

这个错误是Workerman 判断边界失败,才会提醒的。input 方法为啥是空的,这个是处理数据包的边界的;既然报这个错误,说明你拆包出问题了。

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!