Skynet基础入门例子详解(7)

来源:互联网 发布:约旦语言翻译软件 编辑:程序博客网 时间:2024/06/05 14:47

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"endlocal 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)endlocal 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)endsend_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)    endend
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

socket1.lua代码:

local skynet = require "skynet"local common = require "common"local gateskynet.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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

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处理该消息")    endendfunction 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 })endfunction handler.disconnect(fd)    print(fd.."-断开连接")endfunction handler.error(fd, msg)    print("异常错误")endgateserver.start(handler)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

service1.lua代码:

local common = require "common"local skynet = require "skynet"require "skynet.manager"    -- import skynet.registerlocal CMD = {}local client_fdlocal host-- TODO-- skynet.register_protocol-- 注册新的消息类别 PTYPE_CLIENT,新的类别必须提供 pack 和 unpack 函数,用于消息的编码和解码。function CMD.start(conf)    print("service1 CMD.start")    -- common:dump(conf)    -- SOCKET处理endfunction CMD.disconnect()    -- todo: do something before exit    skynet.exit()endskynet.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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

项目源码:http://download.csdn.net/detail/uisoul/9806650 
API参考文档:https://github.com/cloudwu/skynet/wiki/GateServer

0 0
原创粉丝点击