forked from php/doc-zh
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprotocol.xml
More file actions
131 lines (125 loc) · 5.2 KB
/
Copy pathprotocol.xml
File metadata and controls
131 lines (125 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 60ce1c5c7cc6d340191828de21f1d6b48cd83807 Maintainer: laruence Status: ready -->
<chapter xml:id="yar.protocol" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Yar 协议</title>
<simpara>
Yar 不依赖 schema 或 IDL 文件:网络上传输的一切都是纯字节。
任何能够读写字节的语言都可以与 Yar 服务通信,完全不需要安装任何框架——
只需构造一个固定大小的二进制请求头和一个序列化后的请求体,
把它们发送到服务 URI,再解析响应即可。
</simpara>
<simpara>
一条消息由一个固定大小为 82 字节的头部和紧随其后的消息体组成。
头部的布局与下面的 C 结构体完全一致,紧凑排列、没有填充字节,
并按声明顺序逐个字段写入网络:
</simpara>
<programlisting role="c">
<![CDATA[
typedef struct _yar_header {
uint32_t id; /* transaction id */
uint16_t version; /* protocol version, currently always 0 */
uint32_t magic_num; /* must be 0x80DFEC60 */
uint32_t reserved;
unsigned char provider[32]; /* request from whom (authentication) */
unsigned char token[32]; /* request token (authentication) */
uint32_t body_len; /* length of the whole body, including
the packager identifier */
} __attribute__ ((packed)) yar_header_t;
]]>
</programlisting>
<simpara>
其中 <literal>id</literal>、<literal>magic_num</literal>、<literal>reserved</literal>
和 <literal>body_len</literal> 字段以网络字节序(大端)存储;
其余字段是原始字节。
</simpara>
<simpara>
消息体以一个 8 字节的打包器标识符开头——<literal>PHP</literal>、<literal>JSON</literal>
或 <literal>MSGPACK</literal>,不足部分以零填充——用于告知接收方其余内容的编码方式,
其后是序列化内容本身。
</simpara>
<itemizedlist>
<listitem>
<simpara>
请求体解码后是一个数组,包含以下键:<literal>i</literal>(事务 id)、<literal>m</literal>
(被调用的方法)和 <literal>p</literal>(参数列表)。
</simpara>
</listitem>
<listitem>
<simpara>
响应体解码后是一个数组,包含以下键:<literal>i</literal>(事务 id)、<literal>s</literal>
(状态,取值为 <literal>YAR_ERR_*</literal> 常量之一)、<literal>r</literal>(返回值)、
<literal>o</literal>(服务方法产生的任何输出)以及 <literal>e</literal>
(调用失败时的错误或异常)。
</simpara>
</listitem>
</itemizedlist>
<simpara>
通过 HTTP 传输时,消息作为 POST 请求的正文发送,响应作为回复的正文到达;
通过 TCP 或 Unix socket 传输时,消息直接写入流中。
</simpara>
<example>
<title>在不安装扩展的情况下调用 Yar 服务</title>
<simpara>
下面这个独立脚本仅使用标准 socket,就为 <literal>php</literal>
打包器构造了一个有效的 Yar 请求,将其发送到服务 URI,
并输出解码后的响应。用
<link linkend="yar.examples">示例</link>中的
<classname>Operator</classname> 服务运行该脚本,输出为
<literal>int(3)</literal>。
</simpara>
<programlisting role="php">
<![CDATA[
<?php
$uri = "http://api.example.com/operator.php";
/* 1. the body: packager identifier + serialized request */
$serialized = serialize(array("i" => 1, "m" => "add", "p" => array(1, 2)));
$body = str_pad("PHP", 8, "\0") . $serialized;
/* 2. the header: 82 bytes, multi-byte integers in network byte order */
$header = pack("N", 1) /* id */
. pack("v", 0) /* version */
. pack("N", 0x80DFEC60) /* magic number */
. pack("N", 0) /* reserved */
. str_pad("", 32, "\0") /* provider */
. str_pad("", 32, "\0") /* token */
. pack("N", strlen($body)); /* body length */
/* 3. send it as the body of a POST request */
$stream = stream_context_create(array("http" => array(
"method" => "POST",
"header" => "Content-Type: application/octet-stream\r\n",
"content" => $header . $body,
)));
$reply = file_get_contents($uri, false, $stream);
/* 4. parse the reply: 82-byte header, then the response body */
$response = unserialize(substr($reply, 82 + 8));
var_dump($response["r"]);
?>
]]>
</programlisting>
</example>
<simpara>
一个更完整的纯 PHP 客户端实现位于
<link xlink:href="&url.git.hub;laruence/yar">Yar 源码仓库</link>的
<literal>tools/</literal> 目录中,它还会解码响应头,并支持并发调用。
</simpara>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->