chuck-lua 一個lua網路應用框架

weixin_34253539發表於2015-06-27

chuck是一個單執行緒,非同步的C網路庫.同時匯出了lua介面,可以通過lua方便的編寫網路應用.
下面演示一下如何使用chuck編寫一個簡單的echo服務.

echo.lua

local chuck = require("chuck")
local socket = require("distri.socket")
local engine = require("distri.engine")
local signal = chuck.signal
local signaler = signal.signaler(signal.SIGINT)
local clone     = chuck.packet

local server = socket.stream.listen("127.0.0.1",8010,function (s,errno)
    if s then
        if s:Ok(4096,socket.stream.rawdecoder,function (_,msg,errno)
            if msg then
                s:Send(clone(msg))
            else
                s:Close()
                s = nil
            end
        end) then
            s:SetRecvTimeout(5000)
        end
    end
end)

if server then
    signaler:Register(engine,function ()
        engine:Stop()
    end)
    chuck.RegTimer(engine,1000,function() 
        collectgarbage("collect")   
    end)    
    engine:Run()
end

在命令列下輸入./lua echo.lua,然後通過telnet連線伺服器即可.

chuck提供了面向事件回撥的介面,接下來將會使用lua coroutine中對基本的chuck介面進行封裝,實現一個同步網路應用開發框架.

下面再看一個http server的示例.

http.lua

local chuck  = require("chuck")
local Http   = require("samples.lua.http.http")
local signaler = chuck.signal.signaler(chuck.signal.SIGINT)

signaler:Register(Http.engine,function () 
    print("recv sigint")
    Http.Stop()
end)

local server = Http.HttpServer(function (req,res)
    res:WriteHead(200,"OK", {"Content-Type: text/plain"})
    res:End("hello world!")
end):Listen("127.0.0.1",8010)

if server then
    Http.Run()
end

我最終希望將chuck變成一個可以使用lua來編寫的應用伺服器框架,下面是結合使用luasql生成動態頁面的示例.

mysql.html

<!DOCTYPE html><!--STATUS OK-->
<html>
<head>
</head>

<?lua

local str = [[

<table border="1">]]
local driver  = require "luasql.mysql"
env = driver.mysql()
conn = env:connect("ias_test","root","802802","127.0.0.1",3306)
conn:execute"SET NAMES GB2312"
cur = conn:execute("select id,UserName from user limit 20")
row = cur:fetch("a")
str = str .. [[
<tr>
<td>id</td>
<td>name</td>
</tr>]]
while row do
    str = str .. "<tr><td>" .. row.id .. "</td><td>" .. row.UserName .. "</td></tr>"
    row = cur:fetch("a")
end
str = str .. "</table>

"
conn:close()
env:close() 
return str
/?lua>

</html>

這個html檔案中通過使用<?lua>標籤嵌入了一段lua指令碼,當請求這個頁面的時候,內嵌的lua指令碼將會被執行以生成輸出頁面.

為了讓這個html中的lua指令碼得以正確執行,http.lua將被調整成如下形式:

local chuck  = require("chuck")
local Http   = require("samples.lua.http.http")
local signaler = chuck.signal.signaler(chuck.signal.SIGINT)
local Template = require("samples.lua.http.Template")

signaler:Register(Http.engine,function () 
    print("recv sigint")
    Http.Stop()
end)

--dynamic page
local server = Http.HttpServer(function (req,res)
    res:WriteHead(200,"OK", {"Content-Type: text/html"})
    res:End(Template.Load("samples/lua/http/index.html"))
end):Listen("127.0.0.1",8010)

if server then
    Http.Run()
end

chuck目前正在開發中,歡迎大家提出寶貴的意見.

https://github.com/sniperHW/chuck

相關文章