178 lines
6.4 KiB
Lua
178 lines
6.4 KiB
Lua
|
|
local skynet = require "skynet"
|
||
|
|
local socket = require "skynet.socket"
|
||
|
|
local service = require "skynet.service"
|
||
|
|
require "skynet.manager"
|
||
|
|
local websocket = require "http.websocket"
|
||
|
|
local log = require "Log"
|
||
|
|
local dataType = require "DataType"
|
||
|
|
local errorInfo = require "ErrorInfo"
|
||
|
|
local MaxBuffSize = 409600 --200K
|
||
|
|
local handle = {}
|
||
|
|
local MODE, agentId = ...
|
||
|
|
|
||
|
|
if MODE == "agent" then
|
||
|
|
|
||
|
|
function handle.connect(id)
|
||
|
|
print("ws connect from: " .. tostring(id))
|
||
|
|
end
|
||
|
|
|
||
|
|
function handle.handshake(id, header, url)
|
||
|
|
local addr = websocket.addrinfo(id)
|
||
|
|
print("ws handshake from: " .. tostring(id), "url", url, "addr:", addr)
|
||
|
|
print("----header-----")
|
||
|
|
for k,v in pairs(header) do
|
||
|
|
print(k,v)
|
||
|
|
end
|
||
|
|
print("--------------")
|
||
|
|
end
|
||
|
|
|
||
|
|
function handle.message( sokcketId , msg, msg_type)
|
||
|
|
assert(msg_type == "binary" or msg_type == "text")
|
||
|
|
if "binary" == msg_type then
|
||
|
|
local packetSize = string.sub( msg , 1, 8 ) --获取8位头数据
|
||
|
|
if not packetSize then
|
||
|
|
websocket.close( socket)
|
||
|
|
log.info(string.format("ws客户端主动关闭连接 SocketId %d ", sokcketId ))
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
packetSize = tonumber(packetSize)
|
||
|
|
if not packetSize then
|
||
|
|
websocket.close( socket)
|
||
|
|
log.info(string.format("ws客户端主动关闭连接 SocketId %d ", sokcketId ))
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if packetSize > MaxBuffSize or packetSize <= 0 then
|
||
|
|
websocket.close( socket)
|
||
|
|
log.info(string.format("ws关闭连接 SocketId %d 数据量超过阀值 最大值 %d 或者小于等于0 当前包大小 %d", sokcketId , MaxBuffSize , packetSize))
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local c2sData = {}
|
||
|
|
local s2cData = {}
|
||
|
|
c2sData.netType = dataType.NetType_WebSocket
|
||
|
|
c2sData.socketId = sokcketId
|
||
|
|
c2sData.agentId = tonumber(agentId)
|
||
|
|
|
||
|
|
--获取IP地址
|
||
|
|
local addr = websocket.addrinfo( sokcketId )
|
||
|
|
local pos = string.find(addr,":")
|
||
|
|
addr = string.sub(addr,1,pos - 1)
|
||
|
|
c2sData.addr = addr
|
||
|
|
c2sData.isConnect = true
|
||
|
|
c2sData.data= string.sub( msg ,9, packetSize + 8 )
|
||
|
|
|
||
|
|
if not c2sData.data then
|
||
|
|
websocket.close( socket)
|
||
|
|
log.info(string.format("ws关闭连接 SocketId %d 包数据为空,可能客户端关闭连接", sokcketId))
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
--把消息转发到对应的地方处理
|
||
|
|
local s2cData,retLen = skynet.call("StartServer", "lua","TcpMsg",c2sData )
|
||
|
|
if s2cData then
|
||
|
|
retLen = string.format("%08d",string.len(s2cData))
|
||
|
|
websocket.write(sokcketId, retLen..s2cData , msg_type)
|
||
|
|
end
|
||
|
|
else
|
||
|
|
websocket.write(sokcketId, msg , msg_type)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function handle.ping(id)
|
||
|
|
--log.info("ws ping from: " .. tostring(id) .. "\n")
|
||
|
|
end
|
||
|
|
|
||
|
|
function handle.pong(id)
|
||
|
|
--log.info("ws pong from: " .. tostring(id))
|
||
|
|
end
|
||
|
|
|
||
|
|
function handle.close(id, code, reason)
|
||
|
|
log.info("server disconnect ws close from: " .. tostring(id), code, reason)
|
||
|
|
|
||
|
|
--告诉上层,该玩家已经断线了
|
||
|
|
local c2sData = {}
|
||
|
|
c2sData.netType = dataType.NetType_WebSocket
|
||
|
|
c2sData.socketId = id
|
||
|
|
c2sData.isConnect = false
|
||
|
|
skynet.call("StartServer", "lua","TcpMsg",c2sData)
|
||
|
|
end
|
||
|
|
|
||
|
|
function handle.error(id)
|
||
|
|
log.info("client disconnect or nginx disconnect ws error from: " .. tostring(id))
|
||
|
|
|
||
|
|
--告诉上层,该玩家已经断线了
|
||
|
|
local c2sData = {}
|
||
|
|
c2sData.netType = dataType.NetType_WebSocket
|
||
|
|
c2sData.socketId = id
|
||
|
|
c2sData.isConnect = false
|
||
|
|
skynet.call("StartServer", "lua","TcpMsg",c2sData)
|
||
|
|
end
|
||
|
|
|
||
|
|
skynet.start(function ()
|
||
|
|
skynet.dispatch("lua", function (_,_, sokcketId, protocol, addr)
|
||
|
|
if "WebSocketAgentData" == protocol then --发送数据到客户端
|
||
|
|
local retLen = string.format("%08d",string.len(addr))
|
||
|
|
local isSuc = websocket.write( sokcketId , retLen..addr , "binary" )
|
||
|
|
elseif "WebSocketAgentClose" == protocol then --关闭连接
|
||
|
|
websocket.close( sokcketId )
|
||
|
|
else
|
||
|
|
local ok, err = websocket.accept(sokcketId, handle, protocol, addr)
|
||
|
|
if not ok then
|
||
|
|
log.info(err)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
end)
|
||
|
|
else
|
||
|
|
|
||
|
|
local serverIp , serverPort = ...
|
||
|
|
skynet.start(function()
|
||
|
|
local agent = {}
|
||
|
|
for i= 1, 20 do
|
||
|
|
agent[i] = skynet.newservice(SERVICE_NAME, "agent" , i )
|
||
|
|
end
|
||
|
|
local balance = 1
|
||
|
|
local protocol = "ws"
|
||
|
|
local id = socket.listen(serverIp, serverPort)
|
||
|
|
skynet.error(string.format("Listen websocket port 9948 protocol:%s", protocol))
|
||
|
|
socket.start(id, function(id, addr)
|
||
|
|
print(string.format("accept client socket_id: %s addr:%s", id, addr))
|
||
|
|
skynet.send(agent[balance], "lua", id, protocol, addr)
|
||
|
|
balance = balance + 1
|
||
|
|
if balance > #agent then
|
||
|
|
balance = 1
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
skynet.register("WebSocketAgent")
|
||
|
|
skynet.dispatch("lua", function (_,_, cmd, ...)
|
||
|
|
local socketId , agentId , c2sData = ...
|
||
|
|
local isDo,s2cData = false,{}
|
||
|
|
function Do( c2sData )
|
||
|
|
s2cData.code = errorInfo.Suc
|
||
|
|
if "KickUserOffline" == cmd then
|
||
|
|
skynet.send(agent[ agentId ], "lua", socketId, "WebSocketAgentClose", c2sData)
|
||
|
|
else
|
||
|
|
--服务器向客户端发送的消息
|
||
|
|
skynet.send(agent[ agentId ], "lua", socketId, "WebSocketAgentData", c2sData)
|
||
|
|
end
|
||
|
|
return s2cData
|
||
|
|
end
|
||
|
|
|
||
|
|
isDo,s2cData = pcall( Do, c2sData )
|
||
|
|
local sendMsg,sendLen = 0,0
|
||
|
|
if isDo then
|
||
|
|
sendMsg,sendLen = skynet.pack(s2cData)
|
||
|
|
else
|
||
|
|
print("WebSocket 内部错误信息",s2cData)
|
||
|
|
s2cData ={}
|
||
|
|
s2cData.code = errorInfo.ErrorCode.InnerError
|
||
|
|
sendMsg,sendLen = skynet.pack(s2cData)
|
||
|
|
end
|
||
|
|
--返回去
|
||
|
|
skynet.ret(sendMsg,sendLen)
|
||
|
|
end)
|
||
|
|
end)
|
||
|
|
end
|