From d41c9db019ccbc8a70eb221f897184b919d9d8e4 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Fri, 18 Jul 2014 12:09:05 +0800 Subject: [PATCH] bugfix: update the response fd, when the client reconnect --- examples/login/client.lua | 57 +++++++++++++++++++++---------------- examples/login/msgagent.lua | 1 + lualib/snax/msgserver.lua | 53 +++++++++++++++++++++++----------- 3 files changed, 70 insertions(+), 41 deletions(-) diff --git a/examples/login/client.lua b/examples/login/client.lua index 82b0a182..0ebed6a7 100644 --- a/examples/login/client.lua +++ b/examples/login/client.lua @@ -70,13 +70,10 @@ print("login ok, subid=", subid) ----- connect to game server -local session = 0 - -local function send_request(v) - session = session + 1 +local function send_request(v, session) local s = string.char(bit32.extract(session,24,8), bit32.extract(session,16,8), bit32.extract(session,8,8), bit32.extract(session,0,8)) socket.send(fd , v..s) - return session, v + return v, session end local function recv_response(v) @@ -87,7 +84,7 @@ local function recv_response(v) local c = v:byte(i) session = session + bit32.lshift(c,(-1-i) * 8) end - return ok ~=0 , session, content + return ok ~=0 , content, session end local input = {} @@ -115,32 +112,44 @@ local function readpackage() end end +local text = "echo" local index = 1 -local function echo(text) - print("connect") - local fd = assert(socket.connect("127.0.0.1", 8888)) - input = {} +print("connect") +local fd = assert(socket.connect("127.0.0.1", 8888)) +input = {} - local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index) - local hmac = crypt.hmac64(crypt.hashkey(handshake), secret) +local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index) +local hmac = crypt.hmac64(crypt.hashkey(handshake), secret) - socket.send(fd, handshake .. ":" .. crypt.base64encode(hmac)) +socket.send(fd, handshake .. ":" .. crypt.base64encode(hmac)) - print(readpackage()) - print("===>",send_request(text)) - print("===>",send_request(text .. " again")) - print("<===",recv_response(readpackage())) - print("<===",recv_response(readpackage())) +print(readpackage()) +print("===>",send_request(text,0)) +-- don't recv response +-- print("<===",recv_response(readpackage())) - print("disconnect") - socket.close(fd) -end - -echo "hello" +print("disconnect") +socket.close(fd) index = index + 1 -echo "world" +print("connect again") +local fd = assert(socket.connect("127.0.0.1", 8888)) +input = {} + +local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index) +local hmac = crypt.hmac64(crypt.hashkey(handshake), secret) + +socket.send(fd, handshake .. ":" .. crypt.base64encode(hmac)) + +print(readpackage()) +print("===>",send_request("fake",0)) -- request again (use last session 0, so the request message is fake) +print("===>",send_request("again",1)) -- request again (use new session) +print("<===",recv_response(readpackage())) +print("<===",recv_response(readpackage())) +print("disconnect") +socket.close(fd) + diff --git a/examples/login/msgagent.lua b/examples/login/msgagent.lua index 90b4ac08..fc3a2d5b 100644 --- a/examples/login/msgagent.lua +++ b/examples/login/msgagent.lua @@ -47,6 +47,7 @@ skynet.start(function() skynet.dispatch("client", function(_,_, msg) -- the simple ehco service + skynet.sleep(10) -- sleep a while skynet.ret(msg) end) end) diff --git a/lualib/snax/msgserver.lua b/lualib/snax/msgserver.lua index d1a84f3a..f6804a60 100644 --- a/lualib/snax/msgserver.lua +++ b/lualib/snax/msgserver.lua @@ -212,18 +212,21 @@ function server.start(conf) local request_handler = assert(conf.request_handler) - -- u.response is a struct { message, version, index } + -- u.response is a struct { return_fd , response, version, index } local function retire_response(u) if u.index >= expired_number * 2 then local max = 0 local response = u.response for k,p in pairs(response) do - if p[3] < expired_number then - response[k] = nil - else - p[3] = p[3] - expired_number - if p[3] > max then - max = p[3] + if p[1] == nil then + -- request complete, check expired + if p[4] < expired_number then + response[k] = nil + else + p[4] = p[4] - expired_number + if p[4] > max then + max = p[4] + end end end end @@ -238,14 +241,23 @@ function server.start(conf) local p = u.response[session] if p then -- session can be reuse in the same connection - if p[2] == u.version then + if p[3] == u.version then + local last = u.response[session] u.response[session] = nil p = nil + if last[2] == nil then + local error_msg = string.format("Conflict session %s", crypt.hexencode(session)) + skynet.error(error_msg) + error(error_msg) + end end end if p == nil then + p = { fd } + u.response[session] = p local ok, result = pcall(conf.request_handler, u.username, msg, msg_sz) + result = result or "" -- NOTICE: YIELD here, socket may close. if not ok then skynet.error(result) @@ -254,21 +266,28 @@ function server.start(conf) result = result .. '\1' .. session end - p = { netpack.pack_string(result), u.version, u.index } - if u.response[session] then - skynet.error(string.format("Conflict session %s", crypt.hexencode(session))) - end - u.response[session] = p + p[2] = netpack.pack_string(result) + p[3] = u.version + p[4] = u.index else netpack.tostring(msg, sz) -- request before, so free msg - -- resend response, and update index p[3]. - p[3] = u.index + -- update version/index, change return fd. + -- resend response. + p[1] = fd + p[3] = u.version + p[4] = u.index + if p[2] == nil then + -- already request, but response is not ready + return + end end u.index = u.index + 1 - -- check connect again + -- the return fd is p[1] (fd may change by multi request) check connect + fd = p[1] if connection[fd] then - socketdriver.send(fd, p[1]) + socketdriver.send(fd, p[2]) end + p[1] = nil retire_response(u) end