diff --git a/examples/agent.lua b/examples/agent.lua index a2a0a774..fc41802e 100644 --- a/examples/agent.lua +++ b/examples/agent.lua @@ -4,7 +4,8 @@ local socket = require "socket" local sproto = require "sproto" local bit32 = require "bit32" -local rpc +local host +local send_request local CMD = {} local REQUEST = {} @@ -19,11 +20,10 @@ end function REQUEST:set() print("set", self.what, self.value) local r = skynet.call("SIMPLEDB", "lua", "set", self.what, self.value) - return { ok = true } end function REQUEST:handshake() - return { msg = "Welcome to skynet" } + return { msg = "Welcome to skynet, I will send heartbeat every 5 sec." } end local function request(name, args, response) @@ -47,7 +47,7 @@ skynet.register_protocol { name = "client", id = skynet.PTYPE_CLIENT, unpack = function (msg, sz) - return rpc:dispatch(msg, sz) + return host:dispatch(msg, sz) end, dispatch = function (_, _, type, ...) if type == "REQUEST" then @@ -67,7 +67,15 @@ skynet.register_protocol { } function CMD.start(gate, fd, proto) - rpc = sproto.new(proto):rpc "package" + host = sproto.new(proto.c2s):host "package" + send_request = host:attach(sproto.new(proto.s2c)) + skynet.fork(function() + while true do + send_package(send_request "heartbeat") + skynet.sleep(500) + end + end) + client_fd = fd skynet.call(gate, "lua", "forward", fd) end diff --git a/examples/client.lua b/examples/client.lua index a909ee2e..e9efc160 100644 --- a/examples/client.lua +++ b/examples/client.lua @@ -6,7 +6,8 @@ local bit32 = require "bit32" local proto = require "proto" local sproto = require "sproto" -local rpc = sproto.new(proto):rpc "package" +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)) @@ -52,13 +53,40 @@ local session = 0 local function send_request(name, args) session = session + 1 - local str = rpc:request(name, args, session) + local str = request(name, args, session) send_package(fd, str) print("Request:", session) end local last = "" +local function print_request(name, args) + print("REQUEST", name) + if args then + for k,v in pairs(args) do + print(k,v) + end + end +end + +local function print_response(session, args) + print("RESPONSE", session) + if args then + for k,v in pairs(args) do + print(k,v) + end + end +end + +local function print_package(t, ...) + if t == "REQUEST" then + print_request(...) + else + assert(t == "RESPONSE") + print_response(...) + end +end + local function dispatch_package() while true do local v @@ -67,16 +95,12 @@ local function dispatch_package() break end - local t, session, response = rpc:dispatch(v) - assert(t == "RESPONSE" , "This example only support request , so here must be RESPONSE") - print("response session", session) - for k,v in pairs(response) do - print(k,v) - end + print_package(host:dispatch(v)) end end send_request("handshake") +send_request("set", { what = "hello", value = "world" }) while true do dispatch_package() local cmd = socket.readstdin() diff --git a/examples/proto.lua b/examples/proto.lua index 5cf85b11..31b0c52d 100644 --- a/examples/proto.lua +++ b/examples/proto.lua @@ -1,6 +1,8 @@ local sprotoparser = require "sprotoparser" -local proto = sprotoparser.parse [[ +local proto = {} + +proto.c2s = sprotoparser.parse [[ .package { type 0 : integer session 1 : integer @@ -17,7 +19,7 @@ get 2 { what 0 : string } response { - result 0 : boolean + result 0 : string } } @@ -26,11 +28,17 @@ set 3 { what 0 : string value 1 : string } - response { - ok 0 : boolean - } } ]] +proto.s2c = sprotoparser.parse [[ +.package { + type 0 : integer + session 1 : integer +} + +heartbeat 1 {} +]] + return proto diff --git a/lualib/sproto.lua b/lualib/sproto.lua index a6180b0b..e6acd784 100644 --- a/lualib/sproto.lua +++ b/lualib/sproto.lua @@ -1,11 +1,12 @@ local core = require "sproto.core" +local assert = assert local sproto = {} -local rpc = {} +local host = {} local weak_mt = { __mode = "kv" } local sproto_mt = { __index = sproto } -local rpc_mt = { __index = rpc } +local host_mt = { __index = host } function sproto_mt:__gc() core.deleteproto(self.__cobj) @@ -27,14 +28,14 @@ function sproto.parse(ptext) return sproto.new(pbin) end -function sproto:rpc( packagename ) +function sproto:host( packagename ) packagename = packagename or "package" local obj = { __proto = self, __package = core.querytype(self.__cobj, packagename), __session = {}, } - return setmetatable(obj, rpc_mt) + return setmetatable(obj, host_mt) end local function querytype(self, typename) @@ -89,35 +90,22 @@ local function queryproto(self, pname) end local header_tmp = {} -function rpc:request(name, args, session) - local proto = queryproto(self.__proto, name) - header_tmp.type = proto.tag - header_tmp.session = session - local header = core.encode(self.__package, header_tmp) - - if session then - self.__session[session] = assert(proto.response) - end - - if args then - local content = core.encode(proto.request, args) - return core.pack(header .. content) - else - return core.pack(header) - end -end local function gen_response(self, response, session) return function(args) header_tmp.type = nil header_tmp.session = session local header = core.encode(self.__package, header_tmp) - local content = core.encode(response, args) - return core.pack(header .. content) + if response then + local content = core.encode(response, args) + return core.pack(header .. content) + else + return core.pack(header) + end end end -function rpc:dispatch(...) +function host:dispatch(...) local bin = core.unpack(...) header_tmp.type = nil header_tmp.session = nil @@ -126,26 +114,46 @@ function rpc:dispatch(...) if header.type then -- request local proto = queryproto(self.__proto, header.type) + local result if proto.request then - local result = core.decode(proto.request, content) - if header_tmp.session then - return "REQUEST", proto.name, result, gen_response(self, proto.response, header_tmp.session) - else - return "REQUEST", proto.name, result - end + result = core.decode(proto.request, content) + end + if header_tmp.session then + return "REQUEST", proto.name, result, gen_response(self, proto.response, header_tmp.session) else - if header_tmp.session then - return "REQUEST", proto.name, nil, gen_response(self, proto.response, header_tmp.session) - else - return "REQUEST", proto.name - end + return "REQUEST", proto.name, result end else -- response local session = assert(header_tmp.session, "session not found") local response = assert(self.__session[session], "Unknown session") self.__session[session] = nil - return "RESPONSE", session, core.decode(response, content) + if response == true then + return "RESPONSE", session + else + local result = core.decode(response, content) + return "RESPONSE", session, result + end + end +end + +function host:attach(sp) + return function(name, args, session) + local proto = queryproto(sp, name) + header_tmp.type = proto.tag + header_tmp.session = session + local header = core.encode(self.__package, header_tmp) + + if session then + self.__session[session] = proto.response or true + end + + if args then + local content = core.encode(proto.request, args) + return core.pack(header .. content) + else + return core.pack(header) + end end end