网关和客户端交互

来源:互联网 发布:天津基础网络教研平台 编辑:程序博客网 时间:2024/05/22 15:30

麦迪文

6.2 网关和客户端交互
需要配置网关服务器,客户端和写入与客户端通信的协议
文件目录结构如下:

网关与客户端交互

(1)/test/bin/client/config/config

--集群中服务搜索路径,skynet.newservice()时搜索的路径--添加bin/client/?.lua,这个是为了找到main_client.lua--添加bin/client/service/?.lua , bin/service文件夹里存放client的服务luaservice = "./service/?.lua;./../test/bin/client/?.lua;./../test/bin/client/service/?.lua;"lualoader = "lualib/loader.lua"cpath = "./cservice/?.so"--兼容skynet1.0lua_path = "./lualib/compat10/?.lua;./lualib/?.lua;./lualib/?/?.lua"--这个是集群的IP和端口的配置文件, 放在了bin文件夹下cluster = "./../test/bin/clustername.lua"snax = "./test/?.lua"

(2)/test/bin/client/service/client.lua

package.cpath = "luaclib/?.so"package.path = "lualib/?.lua"if _VERSION ~= "Lua 5.3" then    error "Use lua 5.3"end--发送请求,接收包,解析包,传送包local socket = require "client.socket"local proto = require "teach.proto"local sproto = require "sproto"local host = sproto.new(proto.s2c):host "package"local request = host:attach(sproto.new(proto.c2s)) --sproto.new(type--c2s,s2c)local fd = assert(socket.connect("127.0.0.1", 64000))local function send_package(fd, pack)  --send the package    local package = string.pack(">s2", pack)    socket.send(fd, package)endlocal function unpack_package(text) --unpack the package    local size = #text    if size < 2 then        return nil, text    end    local s = text:byte(1) * 256 + text:byte(2)    if size < s+2 then        return nil, text    end    return text:sub(3,2+s), text:sub(3+s)endlocal function recv_package(last)  --receive package    local result    result, last = unpack_package(last)    if result then        return result, last    end    local r = socket.recv(fd)    if not r then        return nil, last    end    if r == "" then        error "Server closed"    end    return unpack_package(last .. r)endlocal session = 0local function send_request(name, args)    session = session + 1    local str = request(name, args, session)    send_package(fd, str)    print("Request:", session)endlocal last = ""local function print_request(name, args)    print("REQUEST", name)    if args then        for k,v in pairs(args) do            print(k,v)        end    endendlocal function print_response(session, args)    print("RESPONSE", session)    if args then        for k,v in pairs(args) do            print(k,v)        end    endendlocal function print_package(t, ...)    if t == "REQUEST" then        print_request(...)    else        assert(t == "RESPONSE")        print_response(...)    endendlocal function dispatch_package()    while true do        local v        v, last = recv_package(last)        if not v then            break        end        print_package(host:dispatch(v))    endendlocal i = 0while true do    dispatch_package()    send_request("heartbeat",{i=i})    i = i + 1    socket.usleep(5 * 1000000)end

(3)/test/bin/client/main_client.lua

local skynet = require "skynet"local cluster = require "cluster"local snax = require "snax"skynet.start(function()    cluster.open("client")    skynet.newservice("client")end)

(4)/test/bin/gateway/config/config

 thread = 8logger = nil--集群harbor要是0harbor = 0--集群主服务start = "main_gateway"bootstrap = "snlua bootstrap"   -- The service for bootstrap--集群中服务搜索路径,skynet.newservice()时搜索的路径--添加bin/gateway/?.lua,这个是为了找到main_gateway.lua--添加bin/gateway/service/?.lua , bin/service文件夹里存放gateway的服务luaservice = "./service/?.lua;./../test/bin/gateway/?.lua;./../test/bin/gateway/service/?.lua"lualoader = "lualib/loader.lua"cpath = "./cservice/?.so"--兼容skynet1.0lua_path = "./lualib/?/?.lua;./lualib/compat10/?.lua;./lualib/?.lua;"--这个是集群的IP和端口的配置文件, 我放在了bin文件夹下cluster = "./../test/bin/clustername.lua"snax = "./test/?.lua"

(5)/test/bin/gateway/service/gateway.lua

local skynet = require "skynet"local gateserver = require "snax.gateserver"local netpack = require "netpack"local proto = require "teach.proto"local sproto = require "sproto"local driver = require "socketdriver"local sprotoloader = require "sprotoloader"local host = sprotoloader.load(1):host "package"local request = host:attach(sprotoloader.load(2))local connection = {}-- fd -> connection : { fd , client, agent , ip, mode }local handler = {}local REQUEST = {}local function request(name, args, response)    local f = assert(REQUEST[name])    local r = f(args)    if response then        return response(r)    endendfunction REQUEST.heartbeat(args)    return {result = string.format("gate get hearbet %s", args.i)}endlocal function send_package(fd, pack)    local package = string.pack(">s2", pack)    driver.send(fd, package)endfunction handler.open(source, conf)  --监听端口打开初始化,source 是请求来源地址,    --conf 是开启 gate 服务的参数表    skynet.error(string.format("Gateway open source[%d]", source))endfunction handler.message(fd, msg, sz)    --当一个完整的包被切分好后,message 方法被调用    if msg then        local type, name, args, response = host:dispatch(msg, sz)        skynet.error(string.format("type[%s], name[%s]", type, name))        for k, v in pairs(args) do            skynet.error(string.format("args k[%s] v[%s]", k, v))        end        if type == "REQUEST" then            local ok, result  = pcall(request, name, args, response)            if ok then                if result then                    return send_package(fd, result)                end                return nil            else                skynet.error(result)                return nil            end        else            assert(type == "RESPONSE")            error "This example doesn't support request client"        end    endendfunction handler.connect(fd,addr) --fd(socket type)    gateserver.openclient(fd)    skynet.error(string.format("Client fd[%d] connect gateway addr[%s]", fd, addr))endfunction handler.disconnect(fd)    skynet.error(string.format("Client fd[%d] disconnect gateway", fd))    gateserver.closeclient(fd)    connection[fd] = nilendfunction handler.error(fd, msg)    skynet.error(string.format("Gateway error fd[%d] msg[%s]", fd, msg))endfunction handler.warning(fd, size)    skynet.error(string.format("Gateway warning fd[%d] size[%s]", fd, size))endlocal CMD = {}  function handler.command(cmd, source, ...)  --服务处理一些 skynet 内部消息,可以注册 command 方法    local f = assert(CMD[cmd])    return f(...) endgateserver.start(handler)

(6)/test/bin/gateway/service/preload.lua

local skynet = require "skynet"local sprotoparser = require "sprotoparser"local sprotoloader = require "sprotoloader"local proto = require "teach.proto"skynet.start(function()    sprotoloader.save(proto.c2s, 1)    sprotoloader.save(proto.s2c, 2)end)

(7)/test/bin/gateway/main_gateway.lua

local skynet = require "skynet"local cluster = require "cluster"local snax = require "snax"require "skynet.manager"local service_config = require "teach.service_config"skynet.start(function()    cluster.open("gateway")    skynet.uniqueservice("preload")    local gateway = skynet.newservice("gateway")    skynet.name(".gateway", gateway)    pcall(skynet.call, gateway,"lua","open", {        port = service_config["gateway_server"]["port"],        maxclient =1024,        nodelay = true,    })end)

(8)/test/bin/clustername.lua

cluster1 = "0.0.0.0" .. ":" .. "65000"cluster2 = "0.0.0.0" .. ":" .. "65001"client = "0.0.0.0" .. ":" .. "65002"gateway = "0.0.0.0" .. ":" .. "65003"

(9)/test/bin/serverd.sh –启动脚本

killall -9 skynetgnome-terminal  --geometry=80x24+20+10 -x ./skynet  ./../test/bin/gateway/config/config &gnome-terminal  --geometry=80x24+120+10 -x ./skynet  ./../test/bin/client/config/config &

(10)关于与客户端的通信协议,文件结构如下:
把teach目录(包含proto.lua和service_config.lua)放入skynet/lualib下面

teach目录

(1)/skynet/lualib/sproto.lua

local sprotoparser = require "sprotoparser"local proto = {}proto.c2s = sprotoparser.parse [[.package {    type 0 : integer    session 1 : integer}handshake 1 {    response {        msg 0  : string    }}get 2 {    request {        what 0 : string    }    response {        result 0 : string    }}set 3 {    request {        what 0 : string        value 1 : string    }}quit 4 {}heartbeat 5 {    request {        i 0 : string    }       response {        result 0 : string    }}]]proto.s2c = sprotoparser.parse [[.package {    type 0 : integer    session 1 : integer}heartbeat 1 {}]]return proto

(2)/skynet/lualib/service_config.lua

local service_config = {}service_config["gateway_server"] = {    host = "0.0.0.0",    port = 64000,   }return service_config

运行结果:
运行结果