HTTP-FLV协议

实现

实际就是利用了HTTP的分块传输,发送FLV数据,服务器无法知道流长度,所以不会填写Content-Length字段而是携带Transfer-Encoding: chunked字段,这样客户端就会一直接受数据了。

分块传输

编码规则

下面我们来看一下分块传输的编码规则,其实也很简单,同样采用了明文的方式,很类似响应头。

  1. 每个分块包含两个部分,长度头和数据块;
  2. 长度头是以 CRLF(回车换行,即\r\n)结尾的一行明文,用 16 进制数字表示长度;
  3. 数据块紧跟在长度头后,最后也用 CRLF 结尾,但数据不包含 CRLF;
  4. 最后用一个长度为 0 的块表示结束,即“0\r\n\r\n”。

HTTP-FLV协议

 

 范围请求

HTTP支持按范围获取数据,这样就可以实现点播了。需要添加请求头 Range , 它是 HTTP 范围请求的专用字段,格式是“bytes=x-y”,其中的 x 和 y 是以字节为单位的数据范围。

要注意 x、y 表示的是“偏移量”,范围必须从 0 计数,例如前 10 个字节表示为“0-9”,第二个 10 字节表示为“10-19”,而“0-10”实际上是前 11 个字节。

Range 的格式也很灵活,起点 x 和终点 y 可以省略,能够很方便地表示正数或者倒数的范围。假设文件是 100 个字节,那么:

  • “0-”表示从文档起点到文档终点,相当于“0-99”,即整个文件;
  • “10-”是从第 10 个字节开始到文档末尾,相当于“10-99”;
  • “-1”是文档的最后一个字节,相当于“99-99”;
  • “-10”是从文档末尾倒数 10 个字节,相当于“90-99”。

服务器收到 Range 字段后,需要做四件事。

第一,它必须检查范围是否合法,比如文件只有 100 个字节,但请求“200-300”,这就是范围越界了。服务器就会返回状态码 416,意思是“你的范围请求有误,我无法处理,请再检查一下”。

第二,如果范围正确,服务器就可以根据 Range 头计算偏移量,读取文件的片段了,返回状态码“206 Partial Content”,和 200 的意思差不多,但表示 body 只是原数据的一部分。

第三,服务器要添加一个响应头字段 Content-Range,告诉片段的实际偏移量和资源的总大小,格式是“bytes x-y/length”,与 Range 头区别在没有“=”,范围后多了总长度。例如,对于“0-10”的范围请求,值就是“bytes 0-10/100”。

最后剩下的就是发送数据了,直接把片段用 TCP 发给客户端,一个范围请求就算是处理完了。

抓包分析

HTTP-FLV协议

 

 1.请求:

GET /live/livestream.flv HTTP/1.1
User-Agent: Lavf/58.29.100
Accept: */*
Range: bytes=0- // 这里表示从0到数据结束
Connection: close // 表示发送完就结束,不是默认的keep-alive
Host: 10.160.58.155:8080
Icy-MetaData: 1

2.响应:

HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Type: video/x-flv
Server: SRS/3.0.156(OuXuli)
Transfer-Encoding: chunked //表示启用分块传输

这里注意,因为没有Content-length字段,所以wirshark抓包未识别为HTTP,还是TCP,如下图所示。

HTTP-FLV协议

 

3.传输数据

HTTP-FLV协议

 

 我们可以看到就是基于分块传输的flv数据流:

HTTP-FLV协议

 

39是ascii码的9,表示块大小是9;

0d0a就是\r\n,表示分隔符;

上一篇:直播未来属于RTMP还是HTTP?


下一篇:C++调用ffmpeg命令推流【详细代码】