网友通过本文主要向大家介绍了luasocket,cocos2dx luasocket,luasocket select,luasocket ipv6,lua 事件等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
lua中使用luasocket通信,写了一个简单的事件库
1.服务端,server.lua。功能有直接转发并执行命令,还有每日定时任务功能和普通定时任务功能,module如下:提供的接口:
server.addrPort(addr,port)
server.runLoop()
- #!/usr/bin/lua
- local socket = require "socket"
- local json = require "cjson.safe"
- local log = require "log"
- local M = {
- headLength = 10,
- address = "0.0.0.0",
- port = 9201,
- io = {},
- timer = {}
- }
- server = M
- --外部调用
- function M.addrPort(addr, port)
- M.address = addr
- M.port = port
- end
- function M.runLoop()
- if (false == M.createServerThread()) then
- log.error("run loop exit")
- return nil
- end
- M.doEvents()
- end
- --内部实现
- function M.createNewIoEvent(_fd, _entry, _func, _event, _data)
- local eventInfo = {
- _fd = _fd,
- _entry = _entry,
- _event = _event,
- _data = _data,
- _func = _func
- }
- log.debug("create new io event, fd (%s), entry (%s), func (%s), event (%s), data (%s)",
- _fd, _entry, _func, _event, _data)
- M.io[#M.io+1] = eventInfo
- end
- function M.createNewTimerEvent(_func, _at, _everyday_at, _interval, _repeat, _data)
- local eventInfo = {
- _func = _func,
- _at = _at,
- _everyday_at = _everyday_at,
- _interval = _interval,
- _repeat = _repeat,
- _data = _data
- }
- log.info("create new timer event, func (%s), at (%s), _everyday_at (%s)," ..
- " interval (%s), repeat (%s), data (%s)",
- _func, _at, _everyday_at, _interval, _repeat, _data)
- M.timer[#M.timer+1] = eventInfo
- end
- function M.executeCommand(cmd)
- local file = assert(io.popen(cmd, 'r'))
- local data = file:read('*all')
- file:close()
- log.info("execute command (%s)", cmd)
- return data
- end
- function M.getEverydaySeconds()
- return tonumber(os.date("%H")) * 3600 +
- tonumber(os.date("%M")) * 60 +
- tonumber(os.date("%S"))
- end
- function M.addTimerTask(_func, _after, _everyday_at, _interval, _repeat, _data)
- local _at
- if (_everyday_at > 0) then
- if (_everyday_at >= M.getEverydaySeconds()) then
- _at = socket.gettime() - M.getEverydaySeconds() + _everyday_at
- else
- _at = socket.gettime() - M.getEverydaySeconds() + _everyday_at + 86400
- end
- log.debug("add new everyday timer task. everyday at (%s)", _at)
- else
- _at = socket.gettime() + _after
- log.debug("add new interval timer task. at (%s)", _at)
- end
- M.createNewTimerEvent(_func, _at, _everyday_at, _interval, _repeat, _data)
- return ""
- end
- function M.removeTimerTask(_data)
- local timer = M.timer
- for i=#timer, 1, -1 do
- if (timer[i]._data == _data) then
- log.info("remove timer task, data (%s)", _data)
- table.remove(timer, i)
- end
- end
- return ""
- end
- function M.packetStringData(s)
- local length = #s
- if (length >= 2^32) then
- return nil
- end
- local head = string.format("%0."..tostring(M.headLength).."u", #s)
- return head .. s
- end
- function M.packetAndSendData(_data, fd)
- local cmd = {
- cmd = 0,
- data = _data
- }
- local data = M.packetStringData(json.encode(cmd))
- local event = "closed"
- if (not data) then
- log.error("failed to packet data, data is to large. length (%s)", _data)
- end
- log.info("packet data successfully, start to send. fd (%s), data (%s)", fd, data)
- while true do
- --socket.sleep(1)
- fd:settimeout(0)
- local count, status = fd:send(data)
- if (status == "timeout") then
- log.info("send data timeout, now yield. fd (%s)", fd)
- coroutine.yield(fd)
- elseif (status == "closed") then
- log.info("closed by peer, fd (%s)", fd)
- event = "closed"
- break
- end
- if (nil ~= count) then
- if (count == #data) then
- log.info("send data completed, contine to read other command, fd (%s)", fd)
- event = "read"
- break
- else
- data = string.sub(data, count+1, -1)
- log.debug("send total %s, remain data (%s), fd (%s)", count, data, fd)
- end
- end
- end
- return event
- end
- function M.receiveAndParseData(fd)
- local event, rest
- local headlen = M.headLength
- local total = 0
- local data = ""
- log.info("start to receive data, fd (%s)", fd)
- while true do
- --socket.sleep(1)
- if (total == 0) then
- rest = headlen - #data
- else
- rest = total - #data
- end
- fd:settimeout(0)
- local s, status, partial = fd:receive(rest)
- local receive = (s or partial)
- data = data .. receive
- log.debug("new receive (%s), fd (%s)", receive, fd)
- if (#receive == 0) then -- partial is a string, so receive is a string
- if status == "timeout" then
- log.info("receive data timeout, now yield. fd (%s)", fd)
- coroutine.yield(fd)
- elseif status == "closed" then
- log.info("closed by peer, fd (%s)", fd)
- event = "closed"
- data = ""
- break
- end
- end
- if (#data >= 10) and (total == 0) then
- total = tonumber(string.sub(data, 1, 10))
- data = string.sub(data, 11, -1)
- log.info("receive head completed, len (%s), data len (%s)", 10, total)
- end
- if (#data > 0) and (#data == total) then
- log.info("receive data completed, len (%s), data (%s)", #data, data)
- event = "pending"
- data = data
- break
- end
- end
- return event, data
- end
- function M.findInfoNode(fd)
- local pos
- local io_ev = M.io
- for i=1, #io_ev do
- if io_ev[i]._fd == fd then
- pos = i
- break
- end
- end
- return io_ev[pos]
- end
- fu