zoukankan      html  css  js  c++  java
  • 一种简单的客户端更新方案

    在c/s结构的程序中,客户端自动更新是简化部署的一个常见需求.更新实际上做的操作是:

    • 与服务器当前的文件做diff,找出所有变动的文件
    • 下载变动的文件,替换掉本地的文件

    从这两个操作来看,服务器起码要向客户端提供两个功能:

    • 当前有那些文件
    • 下载文件

    其实第一个功能也可以转为下载文件,只要提供描述当前文件列表信息的文件就行了。通常有两种更新模式,增量更新与直接更新。增量更新是指低版本向高版本逐版本更新,这种方式的好处在于,服务器发布新版本时可以直接预生成diff补丁包,客户端直接按照补丁包进行替换,但坏处是:

    • 跨版本比较多时,会进行重复操作
    • 管理起来麻烦,要保存所有历史版本

    直接升级则不会有重复操作,且服务器只要保存一个最新版本即可.本文描述的方案就是直接升级的.

    服务端

    基于文件服务器工作,FTP或者HTTP.用两个json文件来管理版本,app.json和appflist.json.文件服务器上的结构为:

    • 文件服务器根目录
    • app1
    • app2

    app就表示客户端的根目录,每个app里都会有app.json和appflist.json.服务器的开发工作就是生成这两个文件,以及更新app目录.

    app.json

    {"version":"1.0.0","info":"版本信息"}
    
    

    用于描述版本号与版本信息,主要给客户端进行快速判断是否要升级.客户端可以简单的判断版本号是否相等来决定要不要升级.

    appflist.json

    [{"path":"foo.dll","md5":"","ctime":147989119}]
    
    

    用于描述文件列表信息,包含当前版本所有文件信息(除app.json,appflist.json),用于给客户端做diff.

    path 为客户端根目录的相对路径

    客户端

    客户端通过本地的app.json和appflist.json与服务器上的同名文件来决定更新操作。更新时会用ftp://127.0.0.1/app1/foo.dll这样的url去下载文件,url的格式为协议://host:port/app目录/文件路径

    更新分为五个步骤:

    1. 判断是否要更新 通过比对app.json的version来决定是否要更新
    2. diff 下载appflist.json,然后通过md5筛选出增删改的文件
    3. 下载变动的文件 用path和app名下载增改的文件
    4. 本地替换 进行增删改操作
    5. 删除下载的文件

    在更新时要注意用独立的进程操作,因为要替换主程序的文件.

    还有如何处理更新失败的情况,更新失败有两种情况:

    • 更新时程序被强制结束
    • 文件操作时失败

    第一种情况发生时,如果正在替换文件,可能会损坏文件,导致主程序不能正常打开,这个问题不在于文件损坏,而是主程序无法运行,也就不能再次进入更新流程了,如果能进来则把流程重来一次就好了,不能进来时只能让用户手动打开更新程序了.因此这种情况是不需要在客户端写特定代码处理的.
    第二种情况发生时,也直接重试流程,如果一直错,那可能是无操作文件的权限,此时并不会损坏旧文件,因此也不需要特殊处理.


    最后我写了一个shupd实现了这些功能,放在github上,shupd的server部分为一个用来生成app.json,appflist.json,拷贝变动文件的工具;client部分为c实现的动态库。目前基于ftp工作,有兴趣的朋友可以看看.

  • 相关阅读:
    Flink基础之实现WordCount程序(Java版本多种写法)
    Redis 在Springboot 中反序列化 LocalDateTime 时报错
    JVM(五)- 堆
    JVM(四)- 虚拟机栈
    JVM(三)- 程序计数器(PC 寄存器)
    JVM(二)- 运行时数据区概述及线程
    JVM(一)
    phpstudy后门漏洞复现
    primefaces 5.x 表达式注入
    ueditor(v1.4.3)文件上传getshell实战复现
  • 原文地址:https://www.cnblogs.com/watercoldyi/p/6683695.html
Copyright © 2011-2022 走看看