壁虎不会漫步壁虎不会漫步05-15 23:02

网络应用(4):块的概念 | Range

分块来处理,也算是自然的想法,就是化整为零。而于对于文件的下载同样使用这个道理,既可整体下载,也可分块下载。

小程这里以http协议为例,来看一下块的概念与使用。

http的range

http1.0请求与返回文件都是整体,不支持“只拿一部分数据”,服务器也不支持断点续传(因为不支持从某个点开始拿部分数据),对于这个特征你可能已经想到不足--要整个来下,如果失败又要重来,那不是麻烦s了?能不能按块按需地下载啊?

既然你有意见了,那http1.1就开始支持只拿部分数据,也支持断点续传(从某点开始下载部分数据),但这时服务器也可以设置为不支持。

这个“拿部分数据”,在http上,也叫分段、分范围,或直接叫分range,因为在http请求头或响应头使用了Range关键字。

考虑到服务器可能不支持range请求,所以客户端在想分range取数据时,最好先跟服务端确认一下:“大哥你支持range吗?”

如果想测试服务器是否支持range,可以发一个head请求来看一下:

curl -I "https://free-picture1.oss-cn-shenzhen.aliyuncs.com/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8/%E6%8A%93%E5%8C%85/%E4%BF%AE%E6%94%B9%E7%9B%AE%E6%A0%87id.png"

可以看到这样的响应:
带range的响应

注意Accept-Ranges字段,如果值是bytes,就是支持range请求。如果没有这个字段,或者值为none,就是不支持range请求。

如果想整个文件请求,那可以不使用range字段,也可以使用range,如:Range: bytes=0-,比如这样:

curl -I -H "Range: bytes=0-" "https://free-picture1.oss-cn-shenzhen.aliyuncs.com/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8/%E6%8A%93%E5%8C%85/%E4%BF%AE%E6%94%B9%E7%9B%AE%E6%A0%87id.png"

这时是整个文件请求,跟不加range的含义是一样的,但服务器的响应不再是200,而是206(部分数据),但长度还是整个文件的长度:
用range来整体请求

显然这里的重点是,使用range进行分段请求,比如:

curl -I -H "Range: bytes=0-1023" "https://free-picture1.oss-cn-shenzhen.aliyuncs.com/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8/%E6%8A%93%E5%8C%85/%E4%BF%AE%E6%94%B9%E7%9B%AE%E6%A0%87id.png"

这里请求了1024个字节(左闭右闭区间),可以看到这样的响应:
请求1024个字节的响应

“块”的管理

以上用http示例,以range来下载数据块,对于其它协议,比如p2p,一样能够以块来下载数据,而且还必须以块下载才满足业务需求,业务就是老大。

如果是分块下载,那最好有一个块的非业务的基本管理模块。块的基本管理模块的设计,最重要的是选择何种数据结构,对于c++来说,map是还不错的选择。

这个块管理类,应该能add一个块(也就是一个区间),能判断块是否已经存在,等等。

比如,用c++,这个类可以这样声明:

class RangeMgr
{
public:
void addRange(long long pos, long long len);
bool hasRange(long long pos, long long len) const;
private:
std::map<long long, long long> m_ranges;
};

这个range管理类应该按场景来增加功能,比如合并重叠的区间,判断从某个点开始有多少数据,等等,具体由你的应用场景来驱动,我不多话了,但你至少要能提出“块”的概念吧。


Who am I

官场书屋二维码

000
评论