写在前面
skynet 提供了一套 tcp 的 API ,本文将给出简单的回显服务器实现,以及讲解。
文章目录
编译 skynet
拉取 skynet 工程
git clone https://github.com/cloudwu/skynet
编译
make linux
服务框架
agent_mgr
- 负责启动 gate 服务
"L"
表示客服端的消息前带四字节大端序的 msg_sizeskynet.address(skynet.self())
把自己设置为 watchdog ,有新连接通过 text 消息告诉自己port
TCP 监听端口0
将 TCP 数据以默认消息类型传输给agent
256
最多同时连接 256 个 TCP
- 新连接时,启动一个新的
agent
并通知 gatenewservice
创建一个 新的agent
forward
通知 gate 把 TCP 数据转发给agent
start
通知 gate 开始接收数据
- 客户端关闭连接时,回收资源
- 关闭 tcp 连接,回收文件描述符
- 通知
agent
把结束服务
agent
- 接收来自 gate 的 TCP 数据,并回写
socket.write
向 socket 写入数据skynet.ignoreret
忽略消息返回
- 接收来自 agent_mgr 的指令,并执行
注意事项
skynet.write 和 skynet.close 中的 id 并非 linux 中的 fd 。
源代码
agent_mgr 服务
lua
-- agent_mgr.lua
local skynet = require "skynet"
local socket = require "skynet.socket"
local queue = require "skynet.queue"
require "skynet.manager"
local cs = queue()
local connections = {}
local CMD = {
open = function (source, session, _)
local agent = skynet.newservice("agent")
connections[session] = { session = session, agent = agent }
skynet.send(source, "text", "forward", session, skynet.address(agent), skynet.address(source))
skynet.send(source, "text", "start", session)
end,
close = function(_, session, _)
skynet.error("socket close:", session)
socket.close_fd(session)
local connection = connections[session]
connections[session] = nil
skynet.send(connection.agent, "lua", "exit")
end,
}
function init()
skynet.register_protocol({
name = "text",
id = skynet.PTYPE_TEXT,
pack = function (...)
local n = select("#" , ...)
if n == 0 then
return ""
elseif n == 1 then
return tostring(...)
else
return table.concat({...}," ")
end
end,
unpack = skynet.tostring,
dispatch = function (_, source, message)
local session, cmd, parm = string.match(message, "(%d+) (%w+) ?(.*)")
local f = assert(CMD[cmd], cmd)
cs(f, source, tonumber(session), parm)
end
})
end
skynet.init(init)
skynet.start(function()
local port = 8000
local gate = skynet.launch("gate", "L", skynet.address(skynet.self()), port, 0, 256)
assert(gate, string.format("launch zinc_gate on port %s fail", port))
end)
agent 服务
lua
-- agent.lua
local skynet = require "skynet"
local socket = require "skynet.socket"
local queue = require "skynet.queue"
require "skynet.manager"
local cs = queue()
function init()
skynet.register_protocol({
name = "client",
id = skynet.PTYPE_CLIENT,
pack = skynet.tostring,
unpack = skynet.tostring,
dispatch = function(session, source, message)
cs(function()
socket.write(session, message)
skynet.ignoreret()
skynet.error("session:", session, "source:", source, "message:", message)
end)
end,
})
skynet.dispatch("lua", function(_, _, cmd, ...)
local args = ...
cs(function()
local f = skynet[cmd]
f(args)
end)
end)
end
skynet.init(init)
skynet.start(function()
end)
配置文件
lua
-- config.echo
-- 启动多少个工作线程
thread = 8
-- skynet 工作在单节点模式下
harbor = 0
-- skynet 节点的主程序
start = "agent_mgr"
-- lua 服务所在的位置
luaservice = "./service/?.lua"
cservice = "./cservice/?.so"