webman 如何返回特殊值 ,已经写到webman控制器了,response似乎也搞不定,现在不知道如何返回, walkor大神一定要看看!

echo回声

<?php

ini_set('date.timezone','Asia/Shanghai');
ini_set("display_errors","On");
error_reporting(E_ALL);

define('FACESYNC_COMMAND_NONE', 0);
define('FACESYNC_REQUEST_FACE_IDS', 1);
define('FACESYNC_RESPONSE_FACE_IDS', 2);
define('FACESYNC_REQUEST_FACE_FEATURES', 3);
define('FACESYNC_RESPONSE_FACE_FEATURES', 4);
define('FACESYNC_REQUEST_FAREWELL', 5);
define('FACESYNC_RESPONSE_FAREWELL', 6);

/*
注意:

  1. 开发环境 PHP 7.3.5 64位
  2. PHP的字符串与C++的std::string相似,都可以包含二进制数据,允许包含'\0'
  3. 字符编码使用UTF-8
    */

//模拟数据库存放三个人的数据
$test_feature_datas = array(

//张三
array(
    //'u32Flag'=> 0,
    'u32CheckSum'=> 0,  //下面数据的校验码,主要用来判断特征结构是否被更新,可以不计算
    'u64FaceId'=> 11111111,  //faceid
    'u64PersonId'=> 11111111,  //personid
    'u32UpdateTime'=> 0,  //修改时间,主要用来判断特征结构是否被更新
    //'u32FeatureCRC'=> 0,   //特征校验码,可以不计算
    'feature'=> '',    //特征向量,填base64解码后的二进制数据,php的字符串直接可以存放二进制(不需要转十六进制字符)

    'info'=> array(
        //'u32Permission'=> 0, //权限
        'szName'=> '张三',  //姓名
        'szNric'=> '123',   //证件
        'szCardNum'=> '123', //卡号
        //'u32VaildDateBegin'=> 0, //有效期开始时间
        //'u32VaildDateEnd'=> 0,  //有效期结束时间
        //'_reserv'=> '' //保留
    )
),

//李四
array(
    //'u32Flag'=> 0,
    'u32CheckSum'=> 0,  //下面数据的校验码,主要用来判断特征结构是否被更新,可以不计算
    'u64FaceId'=> 22222222,  //faceid
    'u64PersonId'=> 22222222,  //personid
    'u32UpdateTime'=> 0,  //修改时间,主要用来判断特征结构是否被更新
    //'u32FeatureCRC'=> 0,   //特征校验码,可以不计算
    'feature'=> '',    //特征向量,填base64解码后的二进制数据,php的字符串直接可以存放二进制(不需要转十六进制字符)
    'info'=> array(
        //'u32Permission'=> 0, //权限
        'szName'=> '李四',  //姓名
        'szNric'=> '444',   //证件
        'szCardNum'=> '444', //卡号
        //'u32VaildDateBegin'=> 0, //有效期开始时间
        //'u32VaildDateEnd'=> 0,  //有效期结束时间
        //'_reserv'=> '' //保留
    )
),

//陈五
array(
    //'u32Flag'=> 0,
    'u32CheckSum'=> 0,  //下面数据的校验码,主要用来判断特征结构是否被更新,可以不计算
    'u64FaceId'=> 33333333,  //faceid
    'u64PersonId'=> 33333333,  //personid
    'u32UpdateTime'=> 0,  //修改时间,主要用来判断特征结构是否被更新
    //'u32FeatureCRC'=> 0,   //特征校验码,可以不计算
    'feature'=> '',    //特征向量,填base64解码后的二进制数据,php的字符串直接可以存放二进制(不需要转十六进制字符)
    'info'=> array(
        //'u32Permission'=> 0, //权限
        'szName'=> '陈五',  //姓名
        'szNric'=> '555',   //证件
        'szCardNum'=> '555', //卡号
        //'u32VaildDateBegin'=> 0, //有效期开始时间
        //'u32VaildDateEnd'=> 0,  //有效期结束时间
        //'_reserv'=> '' //保留
    )
)

);

class FaceSyncSDK
{
//CRC32校验算法 (要速度快请改查表法,网上没有,我不舍得开源)
function CRC32_Calc($buf, $offset, $length, $seed=0xFFFFFFFF)
{
$polynomial = 0x04c11db7;
$crc = $seed;
for ($i = $offset; $i < $offset + $length; $i++) {
$c = ord($buf[$i]);
$crc ^= ($c << 24);
for ($j = 0; $j < 8; $j++) {
if ($crc & 0x80000000) {
$crc = (($crc << 1) & 0xffffffff) ^ $polynomial;
} else {
$crc = ($crc << 1) & 0xffffffff;
}
}
}
return $crc;
}

//FACE_ID_SET_T 转 二进制
function pack_FACE_ID_SET_T($arr)
{
    $bin = '';
    $bin .= pack('Q', $arr['u64FaceId']);
    $bin .= pack('L', $arr['u32UpdateTime']);
    $bin .= pack('L', $arr['u32CheckSum']);
    return $bin;
}

//二进制 转 FACE_ID_SET_T
function unpack_FACE_ID_SET_T($bin, $offset = 64)
{
    $format = 'Qu64FaceId/Lu32UpdateTime/Lu32CheckSum';
    return unpack($format, $bin, $offset);
}

//FACE_SYNC_CMD_T 转 二进制
function pack_FACE_SYNC_CMD_T($arr)
{
    $bin = '';
    $bin .= pack('L', isset($arr['checksum']) ? $arr['checksum'] : 0);  //构造时可忽略参数
    $bin .= pack('L', $arr['command']);     //命令,必要的参数
    $bin .= pack('L', isset($arr['groupnum']) ? $arr['groupnum'] : 0);  //构造时可忽略参数
    $bin .= pack('a20', isset($arr['serialnum']) ? $arr['serialnum'] : ''); //构造时可忽略参数
    $bin .= pack('a24', isset($arr['_reserv']) ? $arr['_reserv'] : ''); //构造时可忽略参数
    $bin .= pack('L', isset($arr['itemcount']) ? $arr['itemcount'] : 0);    //构造时可忽略参数
    $bin .= pack('L', isset($arr['itemsize']) ? $arr['itemsize'] : 0);  //构造时可忽略参数
    return $bin;
}

//二进制 转 FACE_SYNC_CMD_T
function unpack_FACE_SYNC_CMD_T($bin, $offset = 0)
{
    $format = 'Lchecksum/Lcommand/Lgroupnum/a20serialnum/a24_reserv/Litemcount/Litemsize';
    return unpack($format, $bin, $offset);
}

//FACE_FEATURE_T 转 二进制
function pack_FACE_FEATURE_T($arr)
{
    $bin = '';
    $bin .= pack('L', isset($arr['u32Flag']) ? $arr['u32Flag'] : 0);
    $bin .= pack('L', isset($arr['u32CheckSum']) ? $arr['u32CheckSum'] : 0);

    $bin .= pack('Q', $arr['u64FaceId']);
    $bin .= pack('Q', $arr['u64PersonId']);
    $bin .= pack('L', $arr['u32UpdateTime']);

    $bin .= pack('L', isset($arr['u32FeatureCRC']) ? $arr['u32FeatureCRC'] : 0);

    $bin .= pack('a2048', $arr['feature']);

    //PERSON_INFO_T
    $bin .= pack('L', isset($arr['info']['u32Permission']) ? $arr['info']['u32Permission'] : 0);
    $bin .= pack('a32', isset($arr['info']['szName']) ? $arr['info']['szName'] : '');
    $bin .= pack('a20', isset($arr['info']['szNric']) ? $arr['info']['szNric'] : '');
    $bin .= pack('a24', isset($arr['info']['szCardNum']) ? $arr['info']['szCardNum'] : '');
    $bin .= pack('L', isset($arr['info']['u32VaildDateBegin']) ? $arr['info']['u32VaildDateBegin'] : 0);
    $bin .= pack('L', isset($arr['info']['u32VaildDateEnd']) ? $arr['info']['u32VaildDateEnd'] : 0);
    $bin .= pack('a8', isset($arr['info']['_reserv']) ? $arr['info']['_reserv'] : '');

    return $bin;
}

function parseCommand($inputstream)
{
    $recvcmd = self::unpack_FACE_SYNC_CMD_T($inputstream, 0); 
    //printf("command = 0x%X, checksum = 0x%X\r\n", $recvcmd['command'], $recvcmd['checksum']);
    $checksum = self::CRC32_Calc($inputstream, 4, strlen($inputstream)-4, 0xffffffff);

    if($recvcmd['checksum'] != $checksum){
        //printf("recv_checksum = 0x%X, calc_checksum = 0x%X\r\n", $recvcmd['checksum'], $checksum);

        //if($_SERVER['REQUEST_METHOD'] != 'GET'){
            return;  //校验码错误返回
        //}

    }

    if($recvcmd['command'] == FACESYNC_REQUEST_FACE_IDS){ //收到请求人脸列表命令

        $checksum = 0xffffffff; //初始种子
        $test_feature_datas = $GLOBALS['test_feature_datas']; //模拟读取数据库
        $itemcount = count($test_feature_datas);

        //生成协议头
        $sendcmd = array(
            'command'=> FACESYNC_RESPONSE_FACE_IDS, //回复人脸列表命令
            'itemsize'=> 16,  // FACE_ID_SET_T占16字节
            'itemcount'=> $itemcount
        );
        $cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd);
        $checksum = self::CRC32_Calc($cmddata, 4, 60, $checksum); //计算协议头第4字节开始到末尾的校验码

        //生成附加数据
        $listdata = '';
        foreach($test_feature_datas as $obj){
            $face_id_set = self::pack_FACE_ID_SET_T($obj);  //生成二进制列表项
            $checksum = self::CRC32_Calc($face_id_set, 0, 16, $checksum); //累计校验码
            $listdata .= $face_id_set;  //二进制列表
        }

        $sendcmd['checksum'] = $checksum; //将最终数据包的校验码填入协议头
        $cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd);  //重新封包协议头
        //返回二进制流
        header("Content-Type: application/octet-stream"); 
        echo $cmddata;  //发送协议头
        echo $listdata; //发送附加数据
        //flush();

    }else if($recvcmd['command'] == FACESYNC_REQUEST_FACE_FEATURES){ //收到请求人脸特征命令

        $checksum = 0xffffffff; //初始种子
        $test_feature_datas = $GLOBALS['test_feature_datas']; //模拟读取数据库
        $itemcount = $recvcmd['itemcount'];
        $faceids = unpack("Q{$itemcount}", $inputstream, 64); //解包收到的N个人脸IDs  //这里注意双引号

        //生成协议头
        $sendcmd = array(
            'command'=> FACESYNC_RESPONSE_FACE_FEATURES, //回复人脸特征命令
            'itemsize'=> 2176,  // FACE_FEATURE_T占2176字节
            'itemcount'=> $itemcount
        );
        $cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd);
        $checksum = self::CRC32_Calc($cmddata, 4, 60, $checksum); //计算协议头第4字节开始到末尾的校验码

        //生成附加数据
        $listdata = '';
        $face_feature_item = '';
        //查找客户端发来的faceid(s)对应的特征数据
        $found = false;
        foreach($faceids as $id){
            foreach($test_feature_datas as $obj){
                if($id == $obj['u64FaceId']){
                    $face_feature_item = self::pack_FACE_FEATURE_T($obj); //生成二进制列表项
                    $found = true;
                    break;
                }
            }
            if(!$found){
                $face_feature_item = pack('a2176', '');  //如果faceid刚好不存在则填充2176字节空白数据
            }

            $checksum = self::CRC32_Calc($face_feature_item, 0, 2176, $checksum); //累计校验码
            $listdata .= $face_feature_item;  //二进制列表
        }

        $sendcmd['checksum'] = $checksum; //将最终数据包的校验码填入协议头
        $cmddata = self::pack_FACE_SYNC_CMD_T($sendcmd);  //重新封包协议头
        //返回二进制流
        header("Content-Type: application/octet-stream"); 
        echo $cmddata;  //发送协议头
        echo $listdata; //发送附加数据
        //flush(); 
    }
}

}

//######### Main() ###########
//phpinfo();
//print_r($test_feature_datas);

$inputstream = '';
if($_SERVER['REQUEST_METHOD'] == 'GET')
$inputstream = pack("L16", 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); //GET测试返回人脸列表
else
$inputstream = file_get_contents('php://input'); //POST

$facesync = new FaceSyncSDK();
$facesync->parseCommand($inputstream);

?>

截图

2645 3 0
3个回答

echo回声

上面的文件是原始的数据文件,放到类型tp框架这种控制器是可以的,但是长住内存框架,我就搞不定了

  • 暂无评论
yongdao35

看手册 https://www.workerman.net/doc/webman#/response 应该不难吧

应该是

reutrn response($cmddata.$listdata, 200, ['Content-Type'=>'application/octet-stream']);
  • echo回声 2021-03-23

    多谢大佬,测试过了。,还是不行,返回的是一个流数据

不败少龙

public function hello(Request $request)
{
// 创建一个对象
$response = response();

// .... 业务逻辑省略

// 设置cookie
$response->cookie('foo', 'value');

// .... 业务逻辑省略

// 设置http头
$response->header('Content-Type', 'application/json');
$response->withHeaders([
            'X-Header-One' => 'Header Value 1',
            'X-Header-Tow' => 'Header Value 2',
        ]);

// .... 业务逻辑省略

// 设置要返回的数据
$response->withBody('返回的数据');
return $response;

}

  • echo回声 2021-03-23

    多谢大佬,测试过了。,还是不行,返回的是一个流数据

  • 不败少龙 2021-03-23

    @7810:数据流?是不是你没有转换进制

  • echo回声 2021-03-23

    @4519: 用echo 是直接返回数据流回去的, 如果转换了设备不认,我用response不得,可能是我不知道怎么使用

年代过于久远,无法发表回答
🔝