要实现一个协议之前,你首先得读懂他
读懂的懂是怎么体现
就是举简单的实例,去分析其信息,结合RFC来看,把信息头和信息主体全都归类,就差不多了。
由于最近尝试实现RTSP,因此用RTSP作为实例讲讲
RFC2326就是RTSP的协议说明,可以在各大搜索引擎搜索到这个文档
协议文档虽然比较长,很多人都选择性跳过去看,但有些东西容易被人忽略,这里说一下
譬如
4 RTSP Message
RTSP is a text-based protocol and uses the ISO 10646 character set in
UTF-8 encoding (RFC 2279 [21]). Lines are terminated by CRLF, but
receivers should be prepared to also interpret CR and LF by
themselves as line terminators.
1.这里说RTSP里面都是用文本信息进行交流,这就说明传输是直接用字符串的;
2.而编码是ISO 10646的UTF-8编码方式,这就是跟我们直接在里面搞(C)char的ascii码值一样;
3.行的结束是用CR或LF来标记。
很多人会忽略掉这些,有时候一个协议如果是用UTF-16传输字符或者其它编码方式,那么你直接用ascii写出来的协议实现就不通用了。
现在来看一个例子
C->S: OPTIONS * RTSP/1.0
CSeq: 1
Require: implicit-play
Proxy-Require: gzipped-messages
结合RFC看看,这是一条C->S的请求信息
6 Request
A request message from a client to a server or vice versa includes,
within the first line of that message, the method to be applied to
the resource, the identifier of the resource, and the protocol
version in use.
Request = Request-Line ; Section 6.1
*( general-header ; Section 5
| request-header ; Section 6.2
| entity-header ) ; Section 8.1
CRLF
[ message-body ] ; Section 4.3
这里阐述了request是由什么组成的,这里都是些伪码说明,各种逻辑符号(譬如 *、()、| 等)是表示什么可以参看协议第一第二章的一些说明
Requset-Line是主体,那就继续看到底是些什么
6.1 Request Line
Request-Line = Method SP Request-URI SP RTSP-Version CRLF
Method = "DESCRIBE" ; Section 10.2
| "ANNOUNCE" ; Section 10.3
| "GET_PARAMETER" ; Section 10.8
| "OPTIONS" ; Section 10.1
| "PAUSE" ; Section 10.6
| "PLAY" ; Section 10.5
| "RECORD" ; Section 10.11
| "REDIRECT" ; Section 10.10
| "SETUP" ; Section 10.4
| "SET_PARAMETER" ; Section 10.9
| "TEARDOWN" ; Section 10.7
| extension-method
extension-method = token
Request-URI = "*" | absolute_URI
RTSP-Version = "RTSP" "/" 1*DIGIT "." 1*DIGIT
阐述了request-line就是method + 空格 + request-uri + 空格 + rtsp-version + crlf来表示
而method又有DESCRIBE\ANNOUNCE……等
所以这里可以解读第一行,就是OPTIONS + 空格 + uri(为*) + 空格 + RTSP版本1.0
第二行就是一些询问应答的计数器,是必须的信息;
第三行是Require: implicit-play
然后看RFC最后表里一些汇总,可以看到一些之前没有详细说明的关键字的解释
Header type support methods
Require R req. all
这里表示适用于各种方法,然后再看
12.32 Require
The Require header is used by clients to query the server about
options that it may or may not support. The server MUST respond to
this header by using the Unsupported header to negatively acknowledge
those options which are NOT supported.
This is to make sure that the client-server interaction will
proceed without delay when all options are understood by both
sides, and only slow down if options are not understood (as in the
case above). For a well-matched client-server pair, the interaction
proceeds quickly, saving a round-trip often required by negotiation
mechanisms. In addition, it also removes state ambiguity when the
client requires features that the server does not understand.
Require = "Require" ":" 1#option-tag
表示用来咨询有什么方法,也就是说是用来拓展的,因而这里后面的变量值implicit-play是一个拓展的功能,并非标准里面的,对于不同的客户端和服务器都不一样;
最后一行:Proxy-Require: gzipped-messages
再看RFC的说明
12.27 Proxy-Require
The Proxy-Require header is used to indicate proxy-sensitive features
that MUST be supported by the proxy. Any Proxy-Require header
features that are not supported by the proxy MUST be negatively
acknowledged by the proxy to the client if not supported. Servers
should treat this field identically to the Require field.
See Section 12.32 for more details on the mechanics of this message
and a usage example.
也是用来拓展的
这样就可以完成了实现协议前的基础,可以解读协议