【Skynet】文件传输升级版

来源:互联网 发布:视频格式转换器 mac 编辑:程序博客网 时间:2024/05/22 13:12

上一个socket文件传输过于简单,师傅让我进一步改进,定义包结构,让文件的传输过程更加自由。该实现可以参考./examples/client.lua ,这里面有数据的打包与解包。


这里我设计了一个简易的报文结构。


Length:即Type+Content的长度。

Type:将报文分成两种,一种为信息报文,包含文件名及文件大小,以字符串"01"表示,一种为数据报文,以字符串"02"表示。

Content:即报文内容。


客户端(打包):

package.cpath = "luaclib/?.so"package.path = "lualib/?.lua;examples/?.lua"local socket = require "clientsocket"local host = "127.0.0.1"local port = 8888local path = "/home/mick/"local filename = "bird"local blocksize = 65530#注意报文长度最大不超过65535local datalocal data_len = 0local socket_fd = socket.connect(host, port)local function send_package(pack, pack_type)#打包函数,在报文内容前添加两字节报文类型,两字节长度pack = pack_type .. packpack = string.pack(">s2", pack)socket.send(socket_fd, pack)endprint(path .. filename)local file = io.open(path .. filename, "rb")local len = file:seek("end") #seek("end")将光标跳到文件末尾,需使用seek("set")回到文件首file:seek("set")local timelocal remaintime = math.modf(len / blocksize) + 1remain = len % blocksizedata = filename .. '\n' .. tostring(len)print(len)send_package(data, "01")while time > 0 doif time > 1 thentime = time - 1data = file:read(blocksize)data_len = data_len + #datasend_package(data, "02")print("send:", data_len)elsetime = time - 1data = file:read(remain)data_len = data_len + #datasend_package(data, "02")print("send:", data_len)endendio.close(file)socket.close(socket_fd)



服务器(解包):

local skynet = require "skynet"local socket = require "socket"local path = "/home/mick/"local fileName = ""local fileLen = 0local data = ""local remain = 0local function unpack_package(pack)local size = #pack--print("size:", size)if remain == 0 then#remain是出于如果之前解析的数据报文的内容尚未收集完毕,可以接着收集if size < 4 thenprint ("1111")return false, packendlocal len = pack:byte(1) * 256 + pack:byte(2)--print("len:", len)local pack_type = pack:sub(3, 4)if size < len + 2 thenprint("2222")if pack_type == "02" thenremain = len - (size - 2)data = data .. pack:sub(5)print("==", #data, fileLen, "remain:", remain)return false, ""endreturn false, packendif pack_type == "01" then local index = pack:find("\n", 5)--print("index: ", index)fileName = pack:sub(5, index - 1) .. "_copy"for i = index + 1, 2 + len do--print("i:", i)fileLen = fileLen * 10 + tonumber(pack:sub(i, i))end--print("fileLen:", fileLen)elseif pack_type == "02" thendata = data .. pack:sub(5, 2 + len)--print(data)print("==", #data, fileLen)endif #data == fileLen then#数据收集完毕,退出循环return true, nilendreturn false, pack:sub(3 + len)elsedata = data .. pack:sub(1, remain)local remain_old = remainremain = remain - #pack:sub(1, remain)print("data:", #data, "remain:", remain)if #data == fileLen thenreturn true, nilendreturn false, pack:sub(remain_old + 1)endendlocal function recv_package(fd, addr)socket.start(fd)fileName = ""fileLen = 0data = ""local last = ""local result = falsewhile true doresult, last = unpack_package(last)if result thenbreakendlocal r = socket.read(fd)if r thenlast = last .. relseprint("no data!")endendprint("Over")local file = io.open(path .. fileName, "wb")file:write(data)io.close(file)socket.close(fd)endskynet.start(function()local address = "0.0.0.0"local port = 8888socket_listen = socket.listen(address, port)socket.start(socket_listen, recv_package)end)



有了打包过程,我们就能区分信息报文及数据报文,就可以将这两种报文穿插着发送。最后带所有数据收齐,写入新文件。

原创粉丝点击