SPDY Protocol
by sunchangming
at 2013-05-13 15:49:23
original http://www.udpwork.com/item/9832.html
SPDY可视为在原来的https协议的SSL和HTTP之间新加了一层:
- 请求多路复用。在一个tcp连接上并行发行多个请求。而传统来说,为了并行发起多个HTTP请求就得有多条TCP连接。
- 带优先级的请求。
- 头部压缩
- Server Push 。 这个和websocket中的push不是一个东西。
- Server Hint 服务器主动建议客户端下载某些资源。
总的来说,SPDY分为两层,framing层(TCP层上的帧)和HTTP层。
Once the connection is established, clients and servers exchange framed messages。
frame分为两种:
- control frames
- data frames
无论是哪种类型的frames,都有一个8字节的头部。头部的第一位如果是1,代表是control frame,如果是0,代表是data frame。
control frame的格式:
- control bit: 长度1位,值永远是1。
- Version: 15位。标识spdy的版本号。2或者3。
- Type: 16 位。 是哪种control frame.
- Flags: 8位。 一些标志。具体含义要根据这个control frame的type来决定。
- Length: 24位无符号整数,标识后面data字段的长度。
- Data: 有效负荷。
截至SPDY/3,control frame一共有以下10种:
// Types of Spdy Control Frames. enum SpdyControlType { SYN_STREAM = 1, SYN_REPLY, RST_STREAM, SETTINGS, NOOP, // Because it is valid in SPDY/2, kept for identifiability/enum order. PING, GOAWAY, HEADERS, WINDOW_UPDATE, CREDENTIAL, NUM_CONTROL_FRAME_TYPES };
其中NOOP是在SPDY/2中定义的。在SPDY/3中已经去掉。
Data frames的格式:
- control bit: 长度1位,值永远是0。
- stream-id: 31位的整数,标识stream的id。
- flags: 8位。目前只用到最后一位。 (flags & 0x01) == 1 表示这个frame是当前流的最后一帧。
- Length: 24位无符号整数,标识后面data字段的长度。
- Data: 有效负荷。
无论Data frames还是Control frames,Data之前字段加起来都是固定的64 bits。所以可以用这样的C struct表示一个frame的头部(不含Data部分)
// A SPDY stream id is a 31 bit entity. typedef uint32 SpdyStreamId;// protocol over-the-wire sizes. #pragma pack(push) #pragma pack(1) // A special structure for the 8 bit flags and 24 bit length fields. union FlagsAndLength { uint8 flags_[4]; // 8 bits uint32 length_; // 24 bits }; // The basic SPDY Frame structure. struct SpdyFrameBlock { union { struct { uint16 version_; uint16 type_; } control_; struct { SpdyStreamId stream_id_; } data_; }; FlagsAndLength flags_length_; }; #pragma pack(pop) </pre><p>sizeof(SpdyFrameBlock)应该等于8。</p>
创建Session:
int spdylay_session_client_new(spdylay_session **session_ptr, uint16_t version, const spdylay_session_callbacks *callbacks, void *user_data);
int spdylay_session_server_new(spdylay_session **session_ptr, uint16_t version, const spdylay_session_callbacks *callbacks, void *user_data);流: 流是双向的,由很多帧组成。
- 无论是server还是client,都可以创建流
- 流可以携带一系列的name/value对,作为头部。(这点很像http消息头部)
- 同一个connection上可以并发的传递多个流。
- 流可以在传输完毕前被提前cancel。
流的创建和关闭:
- SYN_STREAM 创建一个新的流
- SYN_REPLY SYN_STREAM的回答。
- RST_STREAM 关闭一个流
无论是server还是client,如果要正常关闭一个TCP连接,那么在关闭前应该发送GOAWAY frame,
<div style="margin-top:8px;padding:6px 0;border-top:1px solid #3cf"> <div style="text-align:center;margin:16px 0;padding:6px;border:0px dashed #999;font-family:arial;font-size:26px;font-weight:bold"> <a href="http://www.udpwork.com/item/9832.html#review_form" title="不喜欢" style="text-decoration:none"> <img src="http://www.udpwork.com//images/thumb_down24.gif" alt=""> <span style="color:#f33">0</span> </a> <a href="http://www.udpwork.com/item/9832.html#review_form" title="喜欢" style="text-decoration:none"> <img src="http://www.udpwork.com//images/thumb_up24.gif" alt=""> <span style="color:#3c3">0</span> </a>