chuck-lua 一个lua网络应用框架

jopen 9年前

原文:http://segmentfault.com/a/1190000002939797

 

chuck是一个单线程,异步的C网络库.同时导出了lua接口,可以通过lua方便的编写网络应用.下面演示一下如何使用chuck编写一个简单的echo服务.

echo.lua

local chuck = require("chuck")  local socket_helper = chuck.socket_helper  local connection = chuck.connection  local packet = chuck.packet  local signal = chuck.signal  local engine  local function sigint_handler()    print("recv sigint")    engine:Stop()  end  local signaler = signal.signaler(signal.SIGINT)  function on_new_client(fd)    print("on new client\n")    local conn = connection(fd,4096)    conn:Add2Engine(engine,function (_,p,err)      if p then        p = packet.clone(p)        print(p)        conn:Send(p,function (_)              print("packet send finish")              conn:Close()              conn = nil              end)      else        conn:Close()        conn = nil      end    end)  end  local fd =  socket_helper.socket(socket_helper.AF_INET,                   socket_helper.SOCK_STREAM,                   socket_helper.IPPROTO_TCP)  socket_helper.addr_reuse(fd,1)  local ip = "127.0.0.1"  local port = 8010  if 0 == socket_helper.listen(fd,ip,port) then    print("server start",ip,port)    local server = chuck.acceptor(fd)    engine = chuck.engine()    server:Add2Engine(engine,on_new_client)    chuck.RegTimer(engine,1000,function() collectgarbage("collect") end)    signaler:Register(engine,sigint_handler)    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目前正在开发中,欢迎大家提出宝贵的意见.

项目主页:http://www.open-open.com/lib/view/home/1435481683263</p> </strong>