Skynet基础入门例子详解(7)
2017-04-07 15:50
393 查看
GateServer的使用
skynet 提供了一个通用模板 lualib/snax/gateserver.lua 来启动一个网关服务器,通过 TCP 连接和客户端交换数据。TCP 基于数据流,但一般我们需要以带长度信息的数据包的结构来做数据交换。gateserver 做的就是这个工作,把数据流切割成包的形式转发到可以处理它的地址。
skynet 提供了一个 lua 库 netpack ,用来把 tcp 流中的数据解析成 长度 + 内容的包。
gateserver就是使用netpack进行包解析。
在同一个目录建立7个文件(config,proto.lua,main.lua,mygate.lua,socket1.lua,service1.lua,client1.lua)
本例子的client1使用前两节的client,代码稍作修改。
client1.lua代码:
package.cpath = "luaclib/?.so" package.path = "lualib/?.lua;myexample/e5/?.lua" if _VERSION ~= "Lua 5.3" then error "Use lua 5.3" end local socket = require "clientsocket" -- 通信协议 local proto = require "proto" local sproto = require "sproto" local host = sproto.new(proto.s2c):host "package" local request = host:attach(sproto.new(proto.c2s)) local fd = assert(socket.connect("127.0.0.1", 8888)) local session = 0 -- 封包(长度+内容) local function send_package(fd, pack) local package = string.pack(">s2", pack) socket.send(fd, package) end local function send_request(name, args) session = session + 1 local str = request(name, args, session) -- socket.send(fd, str) -- 添加数据长度包头,gateserver接收自动判断类型为data(gateserver使用了netpack进行解析) -- skynet 提供了一个 lua 库 netpack ,用来把 tcp 流中的数据解析成 长度 + 内容的包。 send_package(fd,str); print("Request:", session) end send_request("handshake") send_request("say", { name = "soul", msg = "hello world" }) while true do -- 接收服务器返回消息 local str = socket.recv(fd) -- print(str) if str~=nil and str~="" then print("server says: "..str) -- socket.close(fd) -- break; end -- 读取用户输入消息 local readstr = socket.readstdin() if readstr then if readstr == "quit" then send_request("quit") -- socket.close(fd) -- break; else -- 把用户输入消息发送给服务器 send_request("say", { name = "soul", msg = readstr }) end else socket.usleep(100) end end
socket1.lua代码:
local skynet = require "skynet" local common = require "common" local gate skynet.start(function() print("==========Socket Start=========") print("Listen socket :", "127.0.0.1", 8888) -- Socket服务配置 local conf = { address = "127.0.0.1", port = 8888, maxclient = 1024, nodelay = true, } -- common:dump(conf) -- 启动Socket管理网关 gate=skynet.newservice("mygate") -- 打开监听端口 skynet.call(gate, "lua", "open" , conf) end)
mygate.lua代码:
local skynet = require "skynet" local gateserver = require "snax.gateserver" local netpack = require "netpack" local common = require "common" local connection = {} -- fd -> connection : { fd , ip } local handler = {} local agentlist = {} -- 当一个完整的包被切分好后,message 方法被调用。这里 msg 是一个 C 指针、sz 是一个数字,表示包的长度(C 指针指向的内存块的长度)。 function handler.message(fd, msg, sz) print("===========gate handler.message============"..fd) -- common:dump(connection[fd]) local c = connection[fd] local agent = agentlist[fd] if agent then -- skynet.redirect(agent, c.client, "client", 1, msg, sz) print("接收到客户端消息,传给agent服务处理") else print("没有agent处理该消息") end end function handler.connect(fd, addr) print("===========gate handler.connect============") local c = { fd = fd, ip = addr, } -- common:dump(c) -- 保存客户端信息 connection[fd] = c -- 马上允许fd 接收消息(由于下面交给service1处理消息,所以可以在service1准备好再调用) -- 这样可能导致客户端发来的消息丢失,因为service1未准备好的情况下,无法处理消息 gateserver.openclient(fd) agentlist[fd] = skynet.newservice("service1") skynet.call(agentlist[fd], "lua", "start", { fd = fd, addr = addr }) end function handler.disconnect(fd) print(fd.."-断开连接") end function handler.error(fd, msg) print("异常错误") end gateserver.start(handler)
service1.lua代码:
local common = require "common" local skynet = require "skynet" require "skynet.manager" -- import skynet.register local CMD = {} local client_fd local host -- TODO -- skynet.register_protocol -- 注册新的消息类别 PTYPE_CLIENT,新的类别必须提供 pack 和 unpack 函数,用于消息的编码和解码。 function CMD.start(conf) print("service1 CMD.start") -- common:dump(conf) -- SOCKET处理 end function CMD.disconnect() -- todo: do something before exit skynet.exit() end skynet.start(function() print("==========Service1 Start=========") skynet.dispatch("lua", function(session, address, cmd, ...) print("==========Service1 dispatch============"..cmd) local f = CMD[cmd] skynet.ret(skynet.pack(f(...))) end) end)
项目源码:http://download.csdn.net/detail/uisoul/9806650
API参考文档:https://github.com/cloudwu/skynet/wiki/GateServer
相关文章推荐
- Skynet基础入门例子详解(4)
- Skynet基础入门例子详解(3)
- Skynet基础入门例子详解(5)
- Skynet基础入门例子详解(1)
- Skynet基础入门例子详解(5)
- Skynet基础入门例子详解(2)
- Skynet基础入门例子详解(2)
- Skynet基础入门例子详解(7)
- Skynet基础入门例子详解(6)
- Skynet基础入门例子详解(6)
- Skynet基础入门例子详解(3)
- Skynet基础入门例子详解(1)
- Skynet基础入门例子详解(4)
- Struts2入门基础之Action详解(四)
- android基础入门控件详解(4)
- [原]java专业程序代写(qq:928900200),学习笔记之基础入门<Hibernate_配置详解>(三十六)
- android基础入门控件详解(6)
- android基础入门控件详解(5)
- Python学习入门基础教程(learning Python)--3.3 分支语句的条件表达式详解 .
- Linux基础入门及系统管理01-Linux运维核心技能-bash基础特性详解09