• http断点续传原理


    这周完成了一个断点续传的功能。

    我们的游戏里加载地图的逻辑简化而言是这样:

    1.首先用本地的md5文件校验地图文件(很多文件)是否完整。(中间有很多步骤,任何步骤失败都认为地图不完整)

    2.如果完整,直接加载地图。

    3.如果不完整,需要通过一个http协议请求后台服务器传回完整的地图。

    现在要增加一个断点续传的功能。也就是地图下载过程中,如果断网,丢包之类,重启游戏地图会继续下载,而不是重新下载。给服务器减少流量。

    要解决这个问题,要了解以下问题:

    1.正常的http请求流程。

    2.http分段请求的原理。

    3.具体地图下载流程的处理。

    1.http请求的流程 

    客户端发送的请求被封装成请求报文

    请求报文的内容里面包括请求方法,请求地址,http协议版本,请求首部。其中的请求方法就是所谓的Get,Post,Put,Header,Delete,Options,Trace,Connect这些。这里我们无需详细了解。

    服务器收到请求以后,会以响应报文的形式发回客户端。响应报文里面包括了http协议版本,状态码,状态码的原因短语,响应首部,请求的实体主体

    状态码会标记服务端是否正常处理,是个重要的参数。

    我们来看下载地图的请求。

    因为是需要直接请求实体,当然是用Get方法。另外只需要知道Url就行。网络正常的情况下,服务端会返回状态码200。而返回的实体就是地图文件,通常是一个压缩文件.zip,用二进制模式写到一个文件,再用ziplib之类解压。

    2.http分段请求的原理

    那么断点续传怎么做呢。在客户端发起的请求报文里,请求首部里面有个可选参数Range,用来标识只请求实体的一部分。

    格式形如:Range: bytes=500-999,请求500bytes到999bytes。Range: bytes=500-,请求500bytes开始到结束的部分。

    那么断点续传其实就是知道上一次传输的终点,把它作为Range参数的起点,发起请求。

    如果请求首部带有Range参数,那么服务器正常情况会返回状态码206和请求的部分实体。

    3.具体地图下载流程的处理

    地图下载的具体逻辑。我这里这样处理:

    服务器返回的实体内容写到一个临时文件,命名为temp.zip。如果下载完整了,就会把名字改掉,改为map_id.zip。如果不完整就不会改名了。

    所以每次发起请求前,判断是否需要断点续传,只需要判断存不存在temp.zip即可。

    1.首先用本地的md5文件校验地图文件(很多文件)是否完整。(中间有很多步骤,任何步骤失败都认为地图不完整)

    2.如果完整直接使用本地地图。

    3.如果不完整,判断是否存在temp.zip文件。

    4.如果存在,请求头部带有Range参数,起点是temp文件的大小。

    5.如果不存在,默认的请求头部,请求完整的文件。

    中间有一些细节问题。可能和具体的实现框架有关。想象一次研发测试流程:

    1.启动游戏,第一次下载是一次完整下载,下载的过程中断网(下载过程有个回调,回调参数有标识进度的process,在这里打断点,然后断网),把收到的实体(应该是一部分)写到temp.zip。

    2.把网接回,再启动游戏,判断是否有temp.zip,有temp.zip,所以将temp.zip的文件大小作为Range参数的起点,发起部分请求。把收到的实体写入temp.zip,但是这次的写入起点是文件的末尾。把文件改名为map_id.zip。

    这两个情况都是写在一个函数里的,那么怎么判断temp.zip文件是否已经是完整的地图文件呢?要不要改名了呢?

    我这边的框架里面,服务器返回的实体res里面有个error参数,通过这个参数就能知道本次返回的实体,是不是客户端请求的全部实体(包括完整的请求和部分的请求)。

    也就是说如果res里面的error是true,那么最后是不会走到改名那步的。下一次请求还是会走断点续传。反之error是false,那么说明本次请求返回的实体已经完整,最后会走到改名那步。

    另外一个问题。如果服务器上的文件内容变更了,我们还从旧文件的断点位置请求,这样就会出错了。

    这个问题,可以考虑请求首部的If-Range参数和响应首部的ETAG参数。也就是说要客户端记录传回文件的ETAG,下一次请求把此ETAG作为If-Range参数。那么服务器会根据ETAG判断文件是否更新。

    如果有更新,会走全量下载,返回状态码200。如果没有更新,会走部分下载,返回状态码206。

    也可以用其他方法,比如大家约定好,服务器那边地图改变了,地图就换一个名字(用时间戳做地图名字后缀),那么客户端这边请求的名字就会变了。不需要考虑If-Range参数。也不必在客户端记录ETAG。

    引用:

    1.《图解http》

  • 相关阅读:
    mysql query insert中文乱码
    git rebase
    ubuntu下怎么合并windows下分割的zip包
    [Matlab]双线性变换法设计数字带阻滤波器
    [Matlab]双线性变换法设计数字带通滤波器
    [Matlab]双线性变换法设计数字高通滤波器
    [Matlab]双线性变换法设计数字低通滤波器
    [Matlab]四种IIR滤波器纹波特性对比
    [Matlab]椭圆滤波器设计:低通、高通、带通和带阻
    [Matlab]切比雪夫Ⅱ型滤波器设计:低通、高通、带通和带阻
  • 原文地址:https://www.cnblogs.com/yao2yaoblog/p/9059731.html
Copyright © 2020-2023  润新知