luasocket 代码目录下有个 etc/dispatch.lua 模块,实现了一个 luasocket + coroutine 的 non-blocking event dispatch 的模型。
---------------------------------------------------------------------------
-- simple non-blocking echo server
-- depends on luasocket and its /etc/dispatch.lua
local dispatch = require("dispatch")
local handler = dispatch.newhandler() -- 得到一个 handler,对应了一个 readfds, writefds
local host = arg[1] or "*"
local port = arg[2] or 8080
local server = assert(handler.tcp())
assert(server:setoption("reuseaddr", true))
assert(server:bind(host, port))
assert(server:listen(32))
handler:start(function() -- start() 中包裹的函数,就是一个 coroutine 的内容
while true do
local client = assert(server:accept()) -- accept, read, write 都是 non-blocking 的
print("peer connected:", client) -- 通过 coroutine 让其看起来是 block 的
assert(client:settimeout(0))
handler:start(function()
while true do
local line, err = client:receive()
if err and err == 'closed' then
print("peer closed:", client)
return
end
assert(client:send(line.."\n"))
end
end)
end
end)
print(string.format("server start: %s:%d ...", host, port))
while true do
handler:step() -- 内部 socket.select(),并分发事件
end
---------------------------------------------------------------------------
厄,coroutine 虽然看起来很好玩,但随着代码量的累积,如果使用 coroutine 的模块本身有bug,debuging也是个噩梦。
评论