Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
171 lines (129 sloc) 7.24 KB

握手协议

一个RTMP连接以握手开始。这里的握手和其他协议的握手不一样。这里的握手由三个固定大小的块组成,而不是可变大小的块加上头。

客户端(发起连接的一方)和服务端各自发送三个相同的块。这些块如果是客户端发送的话记为C0,C1和C2,如果是服务端发送的话记为S0,S1和S2。

握手步骤

握手开始于客户端发送C0,C1块。

在发送C2之前客户端必须等待接收S1 。

在发送任何数据之前客户端必须等待接收S2。

服务端在发送S0和S1之前必须等待接收C0,也可以等待接收C1。

服务端在发送S2之前必须等待接收C1。

服务端在发送任何数据之前必须等待接收C2。

C0和S0消息格式

C0和S0是单独的一个字节。例如:

 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|    version    |
+-+-+-+-+-+-+-+-+

下面是C0和S0包的字段说明。

  • 版本:8位

    在C0中这个字段表示客户端要求的RTMP版本 。在S0中这个字段表示服务器选择的RTMP版本。本规范所定义的版本是3;0-2是早期产品所用的,已被丢弃;4-31保留在未来使用;32-255不允许使用(为了区分其他以某一字符开始的文本协议)。如果服务无法识别客户端请求的版本,应该返回3。客户端可以选择减到版本3或选择取消握手。

C1和S1消息格式

C1和S1消息有1536字节长,由下列字段组成。

 0                 1                   2                   3
 0 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        time (4 bytes)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        zero (4 bytes)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        random bytes                         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        random bytes (1528 bytes)            |
|                            (cont)                           |
|                              ...                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

下面是C1和S1包的字段说明。

  • 时间:4字节

    本字段包含时间戳。该时间戳应该是发送这个数据块的端点的后续块的时间起始点。可以是0,或其他的任何值。为了同步多个流,端点可能发送其块流的当前值。

  • 零:4字节

    本字段必须是全零。

  • 随机数据:1528字节

    本字段可以包含任何值。因为每个端点必须用自己初始化的握手和对端初始化的握手来区分身份,所以这个数据应有充分的随机性。但是并不需要加密安全的随机值,或者动态值。

C2和S2消息格式

C2和S2消息有1536字节长。只是S1和C1的回复。本消息由下列字段组成。

 0                 1                   2                   3
 0 1 2 3 4 5 6 7 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        time (4 bytes)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        time2 (4 bytes)                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        random echo                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        random echo (1528 bytes)             |
|                            (cont)                           |
|                              ...                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

下面是C2和S2包的字段说明。

  • 时间:4字节

    本字段必须包含对等段发送的时间(对C2来说是S1,对S2来说是C1)。

  • 时间2:4字节

    本字段必须包含先前发送的并被对端读取的包的时间戳。

  • 随机回复:1528字节

    本字段必须包含对端发送的随机数据字段(对C2来说是S1,对S2来说是C1)。

每个对等端可以用时间和时间2字段中的时间戳来快速地估计带宽和延迟。但这样做可能并不实用。

握手时序图

+-----------------------------------------------------------+ 
| +-------------+                           +-------------+ | 
| |   Client    |     TCP/IP Network        |   Server    | | 
| +-------------+            |              +-------------+ | 
|       |                    |                     |        | 
| Uninitialized              |                Uninitialized | 
|       |         C0         |                     |        | 
|       |------------------->|          C0         |        | 
|       |                    |-------------------->|        | 
|       |         C1         |                     |        | 
|       |------------------->|          S0         |        | 
|       |                    |<--------------------|        | 
|       |                    |          S1         |        | 
|  Version sent              |<--------------------|        | 
|       |         S0         |                     |        | 
|       |<-------------------|                     |        | 
|       |         S1         |                     |        | 
|       |<-------------------|                Version sent  | 
|       |                    |          C1         |        | 
|       |                    |-------------------->|        | 
|       |         C2         |                     |        | 
|       |------------------->|          S2         |        | 
|       |                    |<--------------------|        | 
|    Ack sent                |                  Ack sent    | 
|       |         S2         |                     |        | 
|       |<-------------------|                     |        | 
|       |                    |          C2         |        | 
|       |                    |-------------------->|        | 
| Handshake Done             |               Handshake Done |
|       |                    |                     |        |
+-----------------------------------------------------------+

下表描述握手中的状态机。

.. list-table::
   :header-rows: 1

   * - 状态
     - 描述
   * - 未初始化
     - .. line-block::
          在这个状态中发送双方的版本。
          此时客户端和服务端都未初始化。
          客户端在C0包中发送版本号。
          如果服务端支持那个版本,则发送S0和S1作为响应;
          否则,服务端采用适当的行为作为响应,在RTMP规范中应终止连接。
   * - 版本已发送
     - .. line-block::
          在未初始化状态之后客户端和服务端都进入版本已发送状态。
          客户端等待S1包,服务端等待C1包。
          在接收到所等待的包后客户端发送C2包,服务端发送S2包,进入发送确认状态。
   * - 确认发送
     - .. line-block::
          客户端和服务端依次等待S2和C2。
   * - 握手完成
     - .. line-block::
          客户端和服务端发送消息。
You can’t perform that action at this time.