srvProtobufAgent.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. -- 网关agent
  2. local skynet = require "skynet"
  3. local code = require "code"
  4. local nodeUtil = require("utils.nodeUtil")
  5. local protobufUtil = require("utils.protobufUtil")
  6. local CMD = {}
  7. local GATE, WATCHDOG
  8. local mapFd = {} -- MAP, key fd; value {uid=uid, heart=0}
  9. local mapUid2Session = {} -- MAP, key uid; value session
  10. -- 断开非活跃链接
  11. local function l_start_fd_heart_bit()
  12. skynet.fork(
  13. function(...)
  14. while true do
  15. for fd, v in pairs(mapFd) do
  16. if skynet_time() - v.heart >= 60 then
  17. skynet.send(WATCHDOG, "lua", "close", fd, "overTime")
  18. end
  19. end
  20. skynet.sleep(200) -- 20s
  21. end
  22. end
  23. )
  24. end
  25. local function l_request(fd, protoname, args, ...)
  26. local fdInfo = mapFd[fd]
  27. if fdInfo == nil or fdInfo.uid == nil then
  28. -- fd未绑定玩家
  29. return
  30. end
  31. local uid = fdInfo.uid
  32. local session = mapUid2Session[uid]
  33. if not session then
  34. return
  35. end
  36. -- 修改fd心跳时间
  37. fdInfo.heart = skynet_time()
  38. -- 转发给游戏服
  39. args.uid = args.uid or uid
  40. nodeUtil:send_to_node(session.gameNode, session.gameAgent, "c2s_forward", uid, protoname, args, ...)
  41. end
  42. local function l_dispath_msg(fd, msg)
  43. -- 解析协议
  44. local ok, protoname, args, response, session = pcall(protobufUtil.parse_protobuf_data, msg)
  45. if not ok then
  46. return log.error("decode sproto faild")
  47. end
  48. l_request(fd, protoname, args, session)
  49. end
  50. -- 获取玩家fd
  51. local function l_get_user_fd(uid)
  52. if uid == nil then
  53. return
  54. end
  55. local session = mapUid2Session[uid]
  56. if session then
  57. return session.fd
  58. end
  59. end
  60. skynet.register_protocol {
  61. name = "client",
  62. id = skynet.PTYPE_CLIENT,
  63. unpack = skynet.tostring,
  64. dispatch = function(fd, address, msg)
  65. skynet.ignoreret()
  66. l_dispath_msg(fd, msg)
  67. end
  68. }
  69. -- from watchdog
  70. function CMD.login(uid, fd)
  71. GATE = GATE or skynet.queryservice("srvGate")
  72. WATCHDOG = WATCHDOG or skynet.queryservice("wsWatchdog")
  73. local session = mapUid2Session[uid]
  74. if session then
  75. if session.fd then
  76. mapFd[fd] = nil
  77. end
  78. session.fd = fd
  79. else
  80. -- 分配游戏服节点/agent
  81. local gameNode, gameAgent = nodeUtil:user_dispatch_game_node_and_agent(uid)
  82. session = {
  83. fd = fd,
  84. uid = uid,
  85. gateNode = skynet.getenv("nodeName"),
  86. gateAgent = skynet.self(),
  87. gameNode = gameNode,
  88. gameAgent = gameAgent
  89. }
  90. end
  91. local fdInfo = {uid = uid, heart = skynet_time()}
  92. mapFd[fd] = fdInfo
  93. mapUid2Session[uid] = session
  94. -- 通知gameAgent 玩家登陆
  95. local ok = nodeUtil:call_to_game_agent(session.gameNode, session.gameAgent, "login", uid, session)
  96. if not ok then
  97. log.error("uid:%s send game to login error", uid)
  98. return false
  99. end
  100. -- 接收客户端协议
  101. _, ok = pcall(skynet.call, GATE, "lua", "fd_band_agent", fd)
  102. if not ok then
  103. log.error("uid:%s send gate to fd_band_agent", tostring(uid))
  104. return false
  105. end
  106. nodeUtil:user_master_band_node(uid)
  107. return true
  108. end
  109. -- from watchdog
  110. function CMD.logout(uid)
  111. local session = mapUid2Session[uid]
  112. if not session then
  113. return
  114. end
  115. local fd = session.fd
  116. if fd then
  117. mapFd[fd] = nil
  118. end
  119. session.fd = nil
  120. -- 玩家登出
  121. nodeUtil:call_to_game_agent(session.gameNode, session.gameAgent, "logout", uid, session)
  122. nodeUtil:user_master_unband_node(uid)
  123. if uid then
  124. mapUid2Session[uid] = nil
  125. end
  126. end
  127. -- 向玩家发消息
  128. function CMD.s2c(uid, name, msg)
  129. local fd = l_get_user_fd(uid)
  130. if fd == nil then
  131. return
  132. end
  133. -- log.proto("push uid=%s, name=%s, msg=%s", uid, name, tostring(msg))
  134. local data = protobufUtil.pack_push_msg(name, msg)
  135. skynet.send(GATE, "lua", "send_to_client", fd, data)
  136. end
  137. -- 回应客户端请求
  138. function CMD.c2s_response(uid, name, msg, session, ud)
  139. local fd = l_get_user_fd(uid)
  140. if fd == nil then
  141. return
  142. end
  143. if is_empty(name) or msg == nil then
  144. return
  145. end
  146. local data = protobufUtil.pack_response_msg(name, msg, session)
  147. if data == nil then
  148. msg = {code = code.INNER_SERVER_ERROR}
  149. data = protobufUtil.pack_response_msg(name, msg, session)
  150. end
  151. skynet.send(GATE, "lua", "send_to_client", fd, data)
  152. end
  153. -- 踢玩家
  154. function CMD.kick(uid, msg)
  155. local fd = l_get_user_fd(uid)
  156. if fd == nil then
  157. return
  158. end
  159. -- 通知玩家被踢
  160. local data = protobufUtil.pack_push_msg("on_server_code", msg)
  161. skynet.send(GATE, "lua", "send_to_client", fd, data)
  162. -- 关闭链接
  163. skynet.send(WATCHDOG, "lua", "close", fd, "kick")
  164. end
  165. function CMD.recycle()
  166. skynet.exit()
  167. end
  168. function CMD.update_proto()
  169. end
  170. skynet.start(
  171. function()
  172. skynet.dispatch(
  173. "lua",
  174. function(session, address, command, ...)
  175. local f = CMD[command]
  176. if session > 0 then
  177. skynet.ret(skynet.pack(f(...)))
  178. else
  179. f(...)
  180. end
  181. end
  182. )
  183. -- 心跳监听
  184. l_start_fd_heart_bit()
  185. end
  186. )