php request response,[原]PHP-yar拓展源码解读三-request/response篇

请求的底层结构

//yar_request.h

typedef struct _yar_request {

zend_ulong id;

zend_string *method;

zval parameters;

/* following fileds don't going to packager */

zval options;

} yar_request_t;

Yar底层使用yar_request_t来描述一个请求的所有信息.

以以下RPC底层调用为例

/** @var Yar_Client $client */

$client->doSth($parm1,$pram2);

id成员使用mt_rand()生成的随机数填充,用于(弱)唯一标识一个(来回)的 rpc请求。

method 对应着 rpc调用的远程方法,此处为'doSth'

parameters 对应着RPC调用方法中的传参,此处的parameters类型为zval 而不是zval[],是因为yar的方法调用基于PHP的魔术方法__call()。而这里parameters对应__call()的第二个参数变量,即[$parm1,$pram2],或者说...$parameters 等同于$parm1,$pram2

options 对应Yar_Client的配置/$_options属性,包含打包方式,超时时间等,

请求的序列化ZVAL

//yar_request.c

zend_string *php_yar_request_pack(yar_request_t *request, char **msg) /* {{{ */ {

zval zreq;

zend_string *payload;

char *packager_name = NULL;

/* @TODO: this is ugly, which needs options stash in request */

if (IS_ARRAY == Z_TYPE(request->options)) {

zval *pzval;

if ((pzval = zend_hash_index_find(Z_ARRVAL(request->options), YAR_OPT_PACKAGER)) && IS_STRING == Z_TYPE_P(pzval)) {

packager_name = Z_STRVAL_P(pzval);

}

}

array_init(&zreq);

add_assoc_long_ex(&zreq, ZEND_STRL("i"), request->id);

add_assoc_str_ex(&zreq, ZEND_STRL("m"), zend_string_copy(request->method));

if (IS_ARRAY == Z_TYPE(request->parameters)) {

Z_TRY_ADDREF(request->parameters);

add_assoc_zval_ex(&zreq, ZEND_STRL("p"), &request->parameters);

} else {

zval tmp;

array_init(&tmp);

add_assoc_zval_ex(&zreq, ZEND_STRL("p"), &tmp);

}

if (!(payload = php_yar_packager_pack(packager_name, &zreq, msg))) {

zval_ptr_dtor(&zreq);

return NULL;

}

zval_ptr_dtor(&zreq);

return payload;

}

为了能够将一个拓展层面/C层面的yar_request_t能够方便的作为一个zval被打包器打包,yar_request_t会被先用来生成一个具有三个成员的中转php数组--,其中yar_request_t->option成员被舍弃。

生成的IMP数组临时变量如下

//IMP数组

array(

'i'=>yar_request_t->id,

'm'=>‘doSth’,

'p'=>array($parm1,$pram2)

)

打包器会对该IMP数组进行序列化作为payload的正文,具体参考 packager篇和protocol篇。

响应的底层结构

typedef struct _yar_response {

long id;

int status;

zend_string *out;

zval err;

zval retval;

} yar_response_t;

Yar底层使用yar_response_t来描述一个响应的所有信息.

id同yar_request_t->id 同一个RPC调用,request和response的id是相同的

远程服务器的(原)标准输出

错误码,默认的0代表 YAR_ERR_OKEY

服务端发生异常时,status为 0x40 ,此时的err是一个PHP数组,发生异常的时候保存着excetion的相关信息,结构如下

array(

'message'=>$exceprtion->$message,

'code'=>$exceprtion->$code,

'file'=>$exceprtion->$file,

'line'=>$exceprtion->$line,

'_type'=>$exceprtion::class,

)

其他报错的情况下,err为字符串,直接存放服务端的错误msg。

retval 表示远程服务器中rpc方法的返回变量

响应的序列化ZVAL

类似yar_request_t的IMP数组,yar_response_t也有一个对应的中转zval,将isroe数组转换成yar_response_t变量

//ISROE数组

array(

"i" => yar_response_t->id,

"s" =>yar_response_t->status,

"r" => yar_response_t->out,

"o" =>yar_response_t->retval,

"e" => yar_response_t->err,

)

这里可以看下该zval转yar_response_t的代码

//yar_response.c

void php_yar_response_map_retval(yar_response_t *response, zval *ret) /* {{{ */ {

if (IS_ARRAY != Z_TYPE_P(ret)) {

return;

} else {

zval *pzval;

HashTable *ht = Z_ARRVAL_P(ret);

if ((pzval = zend_hash_str_find(ht, ZEND_STRL("i"))) == NULL) {

return;

}

convert_to_long(pzval);

response->id = Z_LVAL_P(pzval);

if ((pzval = zend_hash_str_find(ht, ZEND_STRL("s"))) == NULL) {

return;

}

convert_to_long(pzval);

if ((response->status = Z_LVAL_P(pzval)) == YAR_ERR_OKEY) {

if ((pzval = zend_hash_str_find(ht, ZEND_STRL("o"))) != NULL) {

response->out = Z_STR_P(pzval);

ZVAL_NULL(pzval);

}

if ((pzval = zend_hash_str_find(ht, ZEND_STRL("r"))) != NULL) {

ZVAL_COPY(&response->retval, pzval);

}

} else if ((pzval = zend_hash_str_find(ht, ZEND_STRL("e"))) != NULL) {

ZVAL_COPY(&response->err, pzval);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值