AsyncTcpConnection 作为websocket客户端,无法发送二进制帧数据,发送就会导致连接关闭 已解决

zhou604638018

问题描述

使用 AsyncTcpConnection 异步websocket客户端,连接成功之后,发送文本数据没有问题,发送二进制数据,就会到时连接关闭

# 类文件代码
<?php

namespace plugin\webman\gateway\service;

use support\Log;
use Workerman\Connection\AsyncTcpConnection;

class TentWebsocket
{

    protected string $secretId = 'xxx';
    protected string $secretKey = 'xxx';

    protected string $appId = 'xxx';

    protected string $url;

    /**
     * @var null | AsyncTcpConnection
     */
    protected $connect = null;

    public function __construct()
    {
        // 当前时间戳
        $timestamp = time();
// 签名过期时间,这里设置为当前时间后的有效期,例如600秒
        $expired = $timestamp + 3600;
// 随机正整数
        $nonce = random_int(10000000, 99999999);
        $voiceId = md5(uniqid(microtime(true)));
        Log::info(__METHOD__, ['voiceId' => $voiceId, 'nonce' => $nonce,
            'expired' => $expired, 'secretid' => $this->secretId]);
// 将参数按照字段名的字典顺序排序
        $params = [
            'secretid' => $this->secretId,
            'timestamp' => $timestamp,
            'expired' => $expired,
            'nonce' => $nonce,
            'engine_model_type' => '16k_zh_large',
            'voice_id' => $voiceId,
            'voice_format' => 1,    //pcm
        ];

        ksort($params);

// 拼接签名原文字符串
        $queryString = http_build_query($params);

//wss://
        $wssUrl = "asr.cloud.tencent.com/asr/v2/{$this->appId}?{$queryString}";

// 使用HmacSha1算法生成签名串
        $signature = base64_encode(hash_hmac('sha1', $wssUrl, $this->secretKey, true));
        $this->url = 'ws://' . $wssUrl . '&signature=' . urlencode($signature);

    }

    /**
     * @return AsyncTcpConnection
     * @throws \Exception
     */
    public function test()
    {
        // 创建异步TCP连接
        $connection = new AsyncTcpConnection($this->url);
        $connection->maxSendBufferSize = 1048576 * 20;
        $connection->transport = 'ssl';

        return $connection;

//            $connect->send('{"type":"FINISH"}');

    }

}
# 进程启动
public static function onWorkerStart($worker)
    {

        error_reporting(E_ALL);
        Log::info('进程启动:'.$worker->id);
        if($worker->id === 0){
            Log::info('开启定时器');
            $t = new TentWebsocket();
            $audioFilePath = "/home/www/webman/public/test.pcm"; // 请替换为您的音频文件路径
            $audioData = file_get_contents($audioFilePath);

            $chunkSize = 1280; // 举例,具体大小请参照腾讯云文档
            $totalSize = strlen($audioData);
            for ($i = 0; $i < $totalSize; $i += $chunkSize) {
                self::$audioDatas[] = substr($audioData, $i, $chunkSize);
            }
            Log::info(' count='.count(self::$audioDatas));
            self::$websocket = $t->test();

            self::$websocket->onWebSocketConnect = function (AsyncTcpConnection $connect, $response)  {
                Log::info('腾讯实时asr Connected to Tencent AI Recognition' . $response);    // 这里 正常显示了
                self::$connect = $connect;

            };

// 当接收到数据时
            self::$websocket->onMessage = function (AsyncTcpConnection $connect, $message) {
                Log::info($message);

            };

// 当连接发生错误时
            self::$websocket->onError = function ($connection, $code, $message) {
                Log::error('腾讯实时asr Error ' . $code . ': ' . $message);
            };

// 当连接关闭时
            self::$websocket->onClose = function ($connection) {
                Log::info('腾讯实时asr Connection closed');   //日志显示 这里掉线
                $connection->reConnect();
            };

// 执行连接
            self::$websocket->connect();

            Timer::add(0.04, function (){
                if(is_null(self::$connect)){
                    Log::info('连接为空');
                    return;
                }
                if(self::$times>=count(self::$audioDatas)){
                    return;
                }
                $flag = self::$connect->send(self::$audioDatas[self::$times], true);
                Log::info('发送音频数据:' . self::$times.'flag='.$flag.': count='.count(self::$audioDatas));
                // 发送结束标志
                if (self::$times == (count(self::$audioDatas)-1)) {
                    Log::info('发送结束数据');
                    self::$connect->send('{"type":"end"}');
                }

                self::$times++;
            });
        }

    }
582 1 0
1个回答

彭飞

哥们,你是怎么样解决的,我的情况和你一样,也是发送二进制的话,就会自动中断,我还去阿里云那边确认就是二进制数据的问题,发送json都是正常的。是需要怎么配置?

  • zhou604638018 2024-06-18

    要指定格式为二进制,$this->connect->websocketType = Ws::BINARY_TYPE_ARRAYBUFFER;

×
🔝