美文网首页Lua安卓开发相关cocos2dx
8.Quick-cocos2dx模拟热更新服务器

8.Quick-cocos2dx模拟热更新服务器

作者: 会写诗的翩翩少年 | 来源:发表于2017-07-15 10:20 被阅读40次

    0.前言
      要学习热更新,自然而然要先有个服务器,那么要学服务器的知识么,不必,可以通过简单的ftp服务器进行模拟来实现效果,热更新的服务器无非就是资源清单,和加密过的资源,所以我们模拟的服务器大致也就以下几个功能:
      1.添加要上传的文件或文件夹
      2.将已添加的资源上传至服务器(本想用post方式,但貌似是不可以,就改成文件拷贝了,有弄过的朋友望给个思路)
      3.获取资源信息,对资源进行加密,并拷贝至正式路径
      4.生成资源清单(其中用到了dump函数的知识,不熟可以参照前文

    1.简单的ftp服务器
      本人用的是这个简单FTP Server V1.0 绿色免费版,你们可以根据爱好自行选择,使用方式很简单,配置如下图: 


      启动后,在浏览器输入ftp://localhost/就可以看到效果啦!

    2.使用方式
      完成步骤2,将步骤3的代码拷贝至本地,然后以如下方式调用即可

    local CCPost2Server = require("app.scenes.CCPost2Server")
    CCPost2Server.new()
        :addDir("updCommit")    --此处为相对路径
        :commit()
    

    3.代码阅读
      代码很简单,注释很清晰,阅读建议就是将代码拷贝至sublime(个人感觉看着舒服一些),逐行阅读,开始吧!

    require("lfs")
    local CCPost2Server = class("CCPost2Server")
    
    --服务器根路径
    local PATH_C_SERVER_URL = device.writablePath .. "server/"
    --服务器tmp文件夹路径
    local PATH_C_TMP_URL = device.writablePath .. "server/tmp/"
    --服务器资源清单路径
    local PATH_C_RESLIST_URL = device.writablePath .. "server/ResList"
    
    function CCPost2Server:ctor()
        --记录要上传文件的信息
        self.fileAddedList = {}
    end
    
    --上传文件前要先进行add操作
    function CCPost2Server:addFile(filePath)
        --此处用相对路径,不存在则返回
        filePath = device.writablePath .. filePath
        if not cc.FileUtils:getInstance():isFileExist(filePath) then
            return self
        end
    
        --将要上传的路径进行保存
        self.fileAddedList[#self.fileAddedList + 1] = filePath
        return self
    end
    
    --对要上传的文件夹进行add操作
    function CCPost2Server:addDir(dirPath)
        local traversePath = function(self, dirPath)
            for entry in lfs.dir(dirPath) do
                if entry ~= '.' and entry ~= '..' then
                    local path = dirPath .. '/' .. entry
                    local attr = lfs.attributes(path)
                    assert(type(attr) == 'table')
                    
                    if attr.mode == 'directory' then
                        traversePath(path)
                    else
                       self:addFile(path)
                    end
                end
            end    
        end
    
        --此处即为遍历路径,对路径下的所有文件进行add操作
        traversePath(self, dirPath)
        return self
    end
    
    --将已add过得文件上传至服务器,仅为模拟
    function CCPost2Server:commit(ver)
        --记录要上传的版本
        self.commitVer = ver
    
        --此处为模拟,直接将本地资源,拷贝至ftp服务器tmp路径下
        cc.FileUtils:getInstance():createDirectory(PATH_C_TMP_URL)
        for i, v in ipairs(self.fileAddedList) do
            local nameArr = string.split(v, "/")
            local name = nameArr[#nameArr]
    
            local ret, msg = os.rename(v, PATH_C_TMP_URL .. name)
            if ret == nil then
                print(v .. "上传失败, err msg:" .. msg)
            else
                print(v .. "上传成功")
            end
        end
    
        print("上传结束")
        --生成资源清单ResList 
        self:generateResList()
    end
    
    --生成资源清单ResList
    function CCPost2Server:generateResList()
    
        --遍历服务器tmp路径,获取要上传文件信息
        local traversePath = function(self, dirPath)
            for entry in lfs.dir(dirPath) do
                if entry ~= '.' and entry ~= '..' then
                    local path = dirPath .. '/' .. entry
                    local attr = lfs.attributes(path)
                    assert(type(attr) == 'table')
                    
                    if attr.mode == 'directory' then
                        traversePath(path)
                    else
                        --获取文件信息
                        local md5 = string.lower(crypto.md5file(path))
                        local filePathArr = string.split(path, "/")
                        local fileName = filePathArr[#filePathArr]
                        local fileNameArr = string.split(fileName, ".")
                        local fileSuffix = fileNameArr[#fileNameArr]
    
                        local act = "res"
                        if fileSuffix == "zip" then
                            act = "load"
                        end
    
                        --写入资源清单
                        self.ResList.stage[self.ResList.fileNum + 1] = {}
                        self.ResList.stage[self.ResList.fileNum + 1].name = fileName
                        self.ResList.stage[self.ResList.fileNum + 1].fileCheck = false
                        self.ResList.stage[self.ResList.fileNum + 1].code = md5
                        self.ResList.stage[self.ResList.fileNum + 1].act = act
    
                        --剔除服务器上同名资源,并将其从tmp路径移出
                        os.remove(PATH_C_SERVER_URL .. md5)
                        os.rename(path, PATH_C_SERVER_URL .. md5)
                        self.ResList.fileNum = self.ResList.fileNum + 1
                        self.ResList.fileSize = self.ResList.fileSize + cc.FileUtils:getInstance():getFileSize(PATH_C_SERVER_URL .. md5)
                    end
                end
            end    
        end
    
        --此处为打印table至文件中,参照dump函数进行修改
        local printTb2File = function(value)
            tableName = "ResList"       
            savePath = PATH_C_RESLIST_URL
    
            local desciption = "local " .. tableName
            local nesting = 100
            local lookupTable = {}
            local result = {}
    
            local function _v(v)
                if type(v) == "string" then
                    v = "\"" .. v .. "\""
                end
                return tostring(v)
            end
    
            local function _dump(value, desciption, indent, nest, keylen)
                desciption = desciption or "local list"
                local spc = ""
                if type(keylen) == "number" then
                    spc = string.rep(" ", keylen - string.len(desciption))
                end
                if type(value) ~= "table" then          
                    result[#result +1 ] = string.format("%s%s%s = %s,", indent, desciption, spc, _v(value))
                elseif lookupTable[value] then
                    result[#result +1 ] = string.format("%s%s%s = *REF*", indent, desciption, spc)
                else
                    lookupTable[value] = true
                    if nest > nesting then
                        result[#result +1 ] = string.format("%s%s = *MAX NESTING*", indent, desciption)
                    else
                        if desciption == "" then
                            result[#result +1 ] = string.format("%s{", indent)
                        else
                            result[#result +1 ] = string.format("%s%s = {", indent, desciption)
                        end
                        
                        local indent2 = indent.."    "
                        local keys = {}
                        local keylen = 0
                        local values = {}
                        for k, v in pairs(value) do
                            keys[#keys + 1] = k
                            local vk = _v(k)
                            local vkl = string.len(vk)
                            if vkl > keylen then keylen = vkl end
                            values[k] = v
                        end
                        for i, k in ipairs(keys) do
                            local result = tonumber(k)
                            if result == nil then                       
                                _dump(values[k], k, indent2, nest + 1, keylen)
                            else
                                _dump(values[k], "", indent2, nest + 1, keylen)
                            end
                            
                        end
                        result[#result +1] = string.format("%s},", indent)
                    end
                end
            end
            _dump(value, desciption, "", 1)
            result[#result] = "}"
    
            io.writefile(savePath, "", "wb+")
            for i, line in ipairs(result) do
                io.writefile(savePath, line .. "\n", "a+")
            end
            io.writefile(savePath, "return " .. tableName, "a+")
            self.generateResListOk = true
        end
    
        --获取服务器已有的ResList,没有则新建一个
        if not cc.FileUtils:getInstance():isFileExist(PATH_C_RESLIST_URL) then
            self.ResList = {
                ver = 1,            
                stage = {},
                fileNum = 0,
                fileSize = 0
            }
        else
            self.ResList = dofile(PATH_C_RESLIST_URL)
        end
    
        --版本号加1,将ResList输出至文件
        self.ResList.ver = self.commitVer or self.ResList.ver + 1
        traversePath(self, PATH_C_TMP_URL)
        printTb2File(self.ResList)
    end
    
    return CCPost2Server
    

    相关文章

      网友评论

      本文标题:8.Quick-cocos2dx模拟热更新服务器

      本文链接:https://www.haomeiwen.com/subject/ovyahxtx.html