bugfix: update the response fd, when the client reconnect

This commit is contained in:
Cloud Wu
2014-07-18 12:09:05 +08:00
parent 9421435ac5
commit d41c9db019
3 changed files with 70 additions and 41 deletions

View File

@@ -70,13 +70,10 @@ print("login ok, subid=", subid)
----- connect to game server ----- connect to game server
local session = 0 local function send_request(v, session)
local function send_request(v)
session = session + 1
local s = string.char(bit32.extract(session,24,8), bit32.extract(session,16,8), bit32.extract(session,8,8), bit32.extract(session,0,8)) 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) socket.send(fd , v..s)
return session, v return v, session
end end
local function recv_response(v) local function recv_response(v)
@@ -87,7 +84,7 @@ local function recv_response(v)
local c = v:byte(i) local c = v:byte(i)
session = session + bit32.lshift(c,(-1-i) * 8) session = session + bit32.lshift(c,(-1-i) * 8)
end end
return ok ~=0 , session, content return ok ~=0 , content, session
end end
local input = {} local input = {}
@@ -115,32 +112,44 @@ local function readpackage()
end end
end end
local text = "echo"
local index = 1 local index = 1
local function echo(text) print("connect")
print("connect") local fd = assert(socket.connect("127.0.0.1", 8888))
local fd = assert(socket.connect("127.0.0.1", 8888)) input = {}
input = {}
local handshake = string.format("%s@%s#%s:%d", crypt.base64encode(token.user), crypt.base64encode(token.server),crypt.base64encode(subid) , index) 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 hmac = crypt.hmac64(crypt.hashkey(handshake), secret)
socket.send(fd, handshake .. ":" .. crypt.base64encode(hmac)) socket.send(fd, handshake .. ":" .. crypt.base64encode(hmac))
print(readpackage()) print(readpackage())
print("===>",send_request(text)) print("===>",send_request(text,0))
print("===>",send_request(text .. " again")) -- don't recv response
print("<===",recv_response(readpackage())) -- print("<===",recv_response(readpackage()))
print("<===",recv_response(readpackage()))
print("disconnect") print("disconnect")
socket.close(fd) socket.close(fd)
end
echo "hello"
index = index + 1 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)

View File

@@ -47,6 +47,7 @@ skynet.start(function()
skynet.dispatch("client", function(_,_, msg) skynet.dispatch("client", function(_,_, msg)
-- the simple ehco service -- the simple ehco service
skynet.sleep(10) -- sleep a while
skynet.ret(msg) skynet.ret(msg)
end) end)
end) end)

View File

@@ -212,18 +212,21 @@ function server.start(conf)
local request_handler = assert(conf.request_handler) 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) local function retire_response(u)
if u.index >= expired_number * 2 then if u.index >= expired_number * 2 then
local max = 0 local max = 0
local response = u.response local response = u.response
for k,p in pairs(response) do for k,p in pairs(response) do
if p[3] < expired_number then if p[1] == nil then
response[k] = nil -- request complete, check expired
else if p[4] < expired_number then
p[3] = p[3] - expired_number response[k] = nil
if p[3] > max then else
max = p[3] p[4] = p[4] - expired_number
if p[4] > max then
max = p[4]
end
end end
end end
end end
@@ -238,14 +241,23 @@ function server.start(conf)
local p = u.response[session] local p = u.response[session]
if p then if p then
-- session can be reuse in the same connection -- 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 u.response[session] = nil
p = 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
end end
if p == nil then if p == nil then
p = { fd }
u.response[session] = p
local ok, result = pcall(conf.request_handler, u.username, msg, msg_sz) local ok, result = pcall(conf.request_handler, u.username, msg, msg_sz)
result = result or ""
-- NOTICE: YIELD here, socket may close. -- NOTICE: YIELD here, socket may close.
if not ok then if not ok then
skynet.error(result) skynet.error(result)
@@ -254,21 +266,28 @@ function server.start(conf)
result = result .. '\1' .. session result = result .. '\1' .. session
end end
p = { netpack.pack_string(result), u.version, u.index } p[2] = netpack.pack_string(result)
if u.response[session] then p[3] = u.version
skynet.error(string.format("Conflict session %s", crypt.hexencode(session))) p[4] = u.index
end
u.response[session] = p
else else
netpack.tostring(msg, sz) -- request before, so free msg netpack.tostring(msg, sz) -- request before, so free msg
-- resend response, and update index p[3]. -- update version/index, change return fd.
p[3] = u.index -- 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 end
u.index = u.index + 1 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 if connection[fd] then
socketdriver.send(fd, p[1]) socketdriver.send(fd, p[2])
end end
p[1] = nil
retire_response(u) retire_response(u)
end end