Skip to content

Instantly share code, notes, and snippets.

@cloudfreexiao
Created June 10, 2020 08:34
Show Gist options
  • Save cloudfreexiao/851af8acff4ae5cf225d2ff19a94d327 to your computer and use it in GitHub Desktop.
Save cloudfreexiao/851af8acff4ae5cf225d2ff19a94d327 to your computer and use it in GitHub Desktop.
skynet websocket gate lib
local skynet = require "skynet"
local socket = require "skynet.socket"
local socketdriver = require "skynet.socketdriver"
local websocket = require "http.websocket"
local wsserver = {}
local lfd -- listen socket fd
local maxclient
local client_number = 0
local nodelay = false
local CMD = {}
local connection = {}
function wsserver.openclient(fd)
end
function wsserver.closeclient(fd)
local c = connection[fd]
if c then
connection[fd] = nil
websocket.close(fd)
end
end
function wsserver.start(handler)
assert(handler.message)
assert(handler.connect)
local MSG = {}
local function close_fd(fd)
local c = connection[fd]
if c ~= nil then
connection[fd] = nil
client_number = client_number - 1
end
end
function MSG.connect(fd)
if client_number >= maxclient then
socketdriver.close(fd)
return
end
if nodelay then
socketdriver.nodelay(fd)
end
connection[fd] = true
client_number = client_number + 1
local addr = websocket.addrinfo(fd)
handler.connect(fd, addr)
end
function MSG.handshake(fd, header, url)
end
function MSG.message(fd, msg, msg_type)
assert(msg_type == "binary" or msg_type == "text")
if connection[fd] then
handler.message(fd, msg)
else
skynet.error(string.format("Drop message from fd (%d) : %s", fd, msg))
end
end
function MSG.ping(fd)
end
function MSG.pong(fd)
end
function MSG.close(fd, code, reason)
if fd ~= lfd then
if handler.disconnect then
handler.disconnect(fd)
end
close_fd(fd)
else
lfd = nil
end
end
function MSG.error(fd)
if fd == lfd then
socketdriver.close(fd)
skynet.error("gateserver close listen socket, accpet error:[Socket Error]")
else
if handler.error then
handler.error(fd, "[Socket Error]")
end
close_fd(fd)
end
end
-----------------------------------------------
-----------------------------------------------
function CMD.open(source, conf)
assert(not lfd)
local address = conf.address or "0.0.0.0"
local port = assert(conf.port)
local protocol = conf.protocol or "ws"
maxclient = conf.maxclient or 1024
nodelay = conf.nodelay
lfd = socketdriver.listen(address, port)
socket.start(
lfd,
function(fd, addr)
skynet.error(string.format("accept client socket_fd: %s addr:%s", fd, addr))
local ok, err = websocket.accept(fd, MSG, protocol, addr)
if not ok then
skynet.error("websocket accept error:", err)
end
end
)
end
function CMD.close()
assert(lfd)
socketdriver.close(lfd)
end
skynet.register_protocol {
name = "socket",
id = skynet.PTYPE_SOCKET -- PTYPE_SOCKET = 6
}
skynet.start(
function()
skynet.dispatch(
"lua",
function(_, address, cmd, ...)
local f = CMD[cmd]
if f then
skynet.ret(skynet.pack(f(address, ...)))
else
skynet.ret(skynet.pack(handler.command(cmd, address, ...)))
end
end
)
end
)
end
return wsserver
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment