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目前正在开发中,欢迎大家提出宝贵的意见.
https://github.com/sniperHW/chuck