zoukankan      html  css  js  c++  java
  • 软件更新服务之服务端搭建

    软件更新服务之服务端搭建

    说到软件更新相信大家肯定都不止一次两次见过了吧。在手机上,经常可以看到某某助手或者应用中心提示应用更新,而且会很醒目地告诉你:可以节约多少多少流量。在大家各自的PC上面也不止一次看到这种提示吧。

    “检查到新版本x.x.x,当前版本是x.x.x,是否更新”

     

    PC软件提示更新
    PC软件提示更新

     

     

    Android软件提示更新
    Android软件提示更新

     

    这种软件更新是怎么做到的呢?抛开Android的不说,咱们本次讨论一下PC的软件是如何做到的怎么样?
    其实,流程是十分简单的,大家也是一想就能明白。
    流程如下:

    首先,咱们得先有一部远程服务器吧。用来存放软件更新的文件以及清单文件,以及搭建一个服务用以软件检测是否存在有新版本和下载新文件用
    接着软件客户端,就是你的PC上面要有个服务去检测发现版本更新信息。可以在启动的时候,也可以在你点击软件检查更新的时候去检查版本信息。
    点击更新后,下载清单文件,然后再比较一下清单文件和本地文件的差异,可以检测一下文件的MD5什么的。如果不一样的就下载更新,当然如果是不存在的,就更加得下载下来啦。
    最后就是……你得有网,Internet,晓得吧,木得Internet谈自动更新(增量更新)都是“耍流氓”。。。

    流程图如下:

     

    最最最简单的流程
    最最最简单的流程

     

    OK ,那么这个这么简单的流程咱们搞清楚了吗?
    清楚后,咱们分析一下我们服务器担任的角色。我们今天先不管客户端啦(虽然考虑的时候应该一起考虑,小声bb)
    服务器要起到几个作用:
    1、提供网络服务,就是得有简单文件下载服务和应答服务。
    2、得有个文件夹存放更新文件,里面放更新文件和清单文件。
    3、在网络中任意一个位置都可以访问到,而不仅限于自己的那个路由器……

    所以,我们瞬间就可以想起了Python中自带的那个网络服务。。。但是,用过的人都知道它实在是太简单,难以胜任我们的这个需求啊。所以,这个时候,我们可以选用Flask这个小辣椒啦。什么?你不知道Flask是什么?

     

    就是这个火药筒
    就是这个火药筒
    简单普及一波:其实Flask那个图片不是辣椒啦,人家是装火药的啦
    基于他,我们可以很容易地快速搭建好我们自己定义的服务。
    再扯一下,单纯用这个框架简单地写个服务还是可以能应付一般点的并发量的。。。太大的并发量的话,就得采用其他策略去对付了。所以,我们现在讨论的是不考虑高并发情况的。

     

    代码我直接就放上来吧。注释都有写作用的。
    下面我就简单解释一下各函数的写法思路吧。

            5行

    download,接收filename的参数,表示下载的文件名。获取后,通过flak的内置方法返回所需下载文件即可
    Getfile_md5,接收文件路径作为参数,通过文件路径读取文件,然后通过hashlib计算MD5然后返回
    generate,没有参数,用于更新清单文件。(虽然感觉这个做法有点多余,因为可以多写一个独立的文件处理,管理员上传完文件后再执行一次就OK了D)
    findFile,接收目录路径作为参数,递归查找目标目录里面的文件,如果是文件则计算MD5是目录则递归进去寻找文件。
    check,没有参数,返回当前服务器版本号以及更新信息。

    函数的目的就是这么简单。简简单单几十行就可以把这个服务给实现出来了。后面PC客户端在请求是否有新版本更新的时候,就可以用这个服务脚本来处理了。
    当然,这里面还是有挺多没考虑到的问题的。比如被人家恶意下载导致服务器流量快速被消耗,高并发的状态下,它是否能顶的住?

        python    95行

    # -*- coding: utf-8 -*-
    # @Time    : 4/1/2019 19:27
    # @Author  : MARX·CBR
    # @File    : __init__.py.py
    import pickle
    
    from flask import request, jsonify, send_from_directory, abort, Flask
    import os
    import hashlib
    import json
    
    app = Flask(__name__)
    allfile = []
    md5_list = []
    updateList = {}
    directory = os.getcwd()
    
    
    # 下载文件服务
    @app.route("/<filename>", methods=['GET'])
    def download(filename):
        if request.method == "GET":
            if os.path.isfile(os.path.join('updateFiles', filename)):
                return send_from_directory('updateFiles', filename, as_attachment=True)
            abort(404)
    
    
    # 计算文件MD5
    def Getfile_md5(filename):
        if not os.path.isfile(filename):
            return
        myHash = hashlib.md5()
        f = open(filename, 'rb')
        while True:
            b = f.read(8096)
            if not b:
                break
            myHash.update(b)
        f.close()
        return myHash.hexdigest()
    
    
    # 计算生成新的清单文件
    @app.route("/generateNewConfig", methods=['GET'])
    def generate():
        findFile(directory + '/updateFiles/')
        file_md5_list = json.dumps(updateList)
        print(file_md5_list)
        with open('./updateFiles/listFile', 'wb') as f:
            pickle.dump(updateList, f)
        return_data = {
            'Statu': 'success',
        }
        return jsonify(return_data)
        # file_md5_list=json.load(updateList)
    
    
    # 找到更新文件目录里面的文件以及文件夹、递归寻找
    def findFile(path):
        fsinfo = os.listdir(path)
        for fn in fsinfo:
            temp_path = os.path.join(path, fn)
            if not os.path.isdir(temp_path):
                print('文件路径: {}'.format(temp_path))
                fm = Getfile_md5(temp_path)
                print(fn)
                fn = temp_path.replace(directory + "/updateFiles/", '')
                updateList[fn] = fm
            else:
                findFile(temp_path)
    
    
    # 检查更新版本,该部分尚未够,完善。可以考虑为管理员远程上传文件的时候
    # 将更新说明以json格式一同上传到服务器中,更新时直接读取即可
    @app.route("/checkUpdate", methods=['GET'])
    def check():
        if request.method == "GET":
            return_data = {
                'Version': '0.0.1',
                'Msg': '更新文件,修复初始化卡顿bug
    增加文件预下载功能',
            }
            return jsonify(return_data)
    
    
    # 首页Hello
    @app.route("/", methods=['GET'])
    def hello():
        if request.method == "GET":
            return "Hello MARXCBR"
    
    
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=8080)  # 运行,指定监听地址为 0.0.0.0:8080
                                                                               # 服务器端运行可以让所有地方访问到
    

    今天文章大概就这样了,后续会给出 软件更新服务之客户端怎么玩的文章。咱们从头到尾自己实现一个简单的软件更新服务,哈哈哈。如果本文存在什么纰漏或者问题,欢迎大家留言回复。

  • 相关阅读:
    PTA乙级 (*1034 有理数四则运算 (20分)(string.append()))
    Nginx反向代理部署Node.js应用配置方法
    js处理字符串的用法小结
    从零开始基于webpack搭建react全家桶
    Linux常用指令
    matplotlib作图时中文字体乱码解决办法
    大话数据结构 串
    大话数据结构 队列
    大话数据结构 栈
    大话数据结构 线性表
  • 原文地址:https://www.cnblogs.com/marxcbr/p/10859536.html
Copyright © 2011-2022 走看看