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
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)

View File

@@ -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)

View File

@@ -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