0 创建自己的测试目录
examples同级目录下创建 myexample文件夹,在里面添加study,study文件夹下添加config main.lua service1.lua socket1.lua
client.lua 文件。
1 config 文件,
config是启动skynet的必要配置文件,把example中的config内容整个复制过来添加注释,然后再稍作修改。
skynet会读取config文件获得启动参数,调用skynet-src/skynet_main.c脚本的入口main并传入config
完整代码如下:
root = "./" --根目录
thread = 8 --启动工作的线程数量,一般不要设置超过实际拥有的CPU核心数量
bootstrap = "snlua bootstrap" -- 启动的第一个服务以及其启动参数 bootstrap 会根据luaservice匹配到lua脚本 默认是 :service/bootstrap.lua(其实第一个是logger)
logger = nil --输出到标准输出
logpath = "."
harbor = 1 --1-255之间任意整数,一个skynet网络最多支持255个节点;0表示单节点模式,单节点模式下 后面三行不必设置
address = "127.0.0.1:2526" --当前skynet的地址和端口
master = "127.0.0.1:2013" --master配置项必须和standlone相同
standalone = "0.0.0.0:2013"
start = "main" -- main script 设置bootstrap的最后一个节点(将要启动的lua服务)
luaservice = root.."service/?.lua;"..root.."myexample/study/?.lua"
lualoader = root .. "lualib/loader.lua"
lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"--将添加到package.path中的路径提供给require调用
lua_cpath = root .. "luaclib/?.so"--将添加到pachage.cpath 中的路径提供给require调用
snax = root.."example1/?.lua;"..root.."test/?.lua"
cpath = root.."cservice/?.so" --cservice目录下的 .so 文件
应该非常清晰了,
2 simpledb.lua
service1的代码我是整个从官方 examples下的simpledb.lua 中拷贝过来进行测试的
部分api放在skynet.manager模块中,用到的时候如要引入skynet.manager模块。
skynet.launch --启动launcher服务
skynet.kill --杀掉一个服务(但无法杀掉死循环服务)
skynet.abort --退出进程
skynet.register --注册别名(需要在32字符内)
skynet.name --给服务器命名
skynet. forward_type --将本服务实现为消息转发器,对一类消息进行转发
skynet.filter --过滤消息再处理
skynet.monitor --给当前skynet进程设置一个全局的服务监控
skynet的每个进程被称作一个skynet节点,
skynet.start 一个服务在lua层的入口
skynet.dispatch 注册特定类消息的处理函数
skynet.error 是lua-skynet.c#lerror 函数的别名
skynet.ret 返回命令调用结果,所有通过ret的返回值都要用pack打包
service1完整代码如下
local skynet = require "skynet"--引入skynet库
require "skynet.manager"
local db = {}
local command = {}
--参考 examples simpledb.lua
function command.GET(key)
-- body
print("commant.get" .. key )
return db[key]
end
function command.SET( key,value )
-- body
print("comman.set:key="..key..",value="..value)
local last = db[key]
db[key] = value
return last
end
skynet.start(function ()
-- body
print("====== service1 start ======")
skynet.dispatch("lua",function ( session,address,cmd,...)
-- body
cmd = cmd:upper()
if cmd == "PING" then
assert(session == 0)
local str = (...)
if #str > 20 then
str = str:sub(1,20) .. "...(" .. #str .. ")"
end
skynet.error(string.format("%s ping %s", skynet.address(address), str))
return
end
local f = command[cmd]
if f then
--
skynet.ret(skynet.pack(f(...))) --回应消息
else
error(string.format("Unknown command %s", tostring(cmd)))
end
end)
skynet.register "SERVICE1" --注册一个32字符内的别名
end)
3 main.lua
snlua服务模块:通过解析lua脚本来实现业务逻辑
cluster.reload
skynet.newservice
main完整代码如下:
local skynet = require "skynet"
local cluster = require "skynet.cluster"
local snax = require "skynet.snax"
skynet.start(function ()
print("========== serverStart ==============")
cluster.reload {
db = "127.0.0.1:2527",
db2 = "127.0.0.1:2528",
}
local service1 = skynet.newservice("service1") --启动lua服务
--在内部生成一个唯一的session
--把一类别为 typename的消息发送给address并阻塞等待对session的回应
--在 skynet.call 之前获得的服务内的状态,到返回后,很有可能改变
skynet.call(service1,"lua","SET","a","footbar")
-- --
local kv = skynet.call(service1,"lua","GET","a")
cluster.open "db"
cluster.open "db2"
-- skynet.newservice("socket1")
skynet.exit()
end)
4 运行 执行命令
./skynet ./myexample/study/config
效果如下:
可以看到启动顺序,
snlua bootstrap
snlua launcher
snlua cmaster
实际上第一个启动的服务是logger ,第二个才是bootstrap
bootstrap 是所有lua服务的标准启动入口,传入function参数, funtion方法也是此lua服务在lua层的回调接口,本服务的消息都在function回调方法中执行
snlua会把bootstrap作为参数传递给skynet
snlua 是 lua 沙盒服务,bootstrap 会根据配置的 luaservice 匹配到最终的 lua 脚本。如果按默认配置,这个脚本应该是 service/bootstrap.lua 。
5 服务端与客户端的通信
编辑 socket1.lua client.lua 两个
通讯时 官网提供 sproto 协议, skynet/lualib-src/sproto目录下可见(后面再看)
client完整代码:
local skynetroot = "../skynet/"
package.cpath = skynetroot .. "luaclib/?.so"
package.path = skynetroot .. "lualib/?.lua;study/?.lua"
if _VERSION ~= "Lua 5.3" then
error "[error use lua 5.3]"
end
local socket = require "client.socket"
local fd= assert(socket.connect("127.0.0.1",8800))
socket.send(fd,"hello skynet")--发送一条协议给服务器
socket1完整代码:
local skynet = require "skynet"
local socket = require "skynet.socket"
local function echo( id )
-- body
socket.start(id)
while true do
local str = socket.read(id)
if str then
print(str)
else
socket.close(id)
return
end
end
end
skynet.start(function ( )
-- body
local id = socket.listen("127.0.0.1",8800)
socket.start(id ,function ( id,addr )
-- body
print("connect from addr:" .. addr .. "id:" .. id)
echo(id)
end)
end)
运行服务器:把main.lua修改一下:
local skynet = require "skynet"
local cluster = require "skynet.cluster"
local snax = require "skynet.snax"
skynet.start(function ()
print("========== serverStart ==============")
-- cluster.reload {
-- db = "127.0.0.1:2527",
-- db2 = "127.0.0.1:2528",
-- }
-- local service1 = skynet.newservice("service1") --启动lua服务
-- --在内部生成一个唯一的session
-- --把一类别为 typename的消息发送给address并阻塞等待对session的回应
-- --在 skynet.call 之前获得的服务内的状态,到返回后,很有可能改变
-- skynet.call(service1,"lua","SET","a","footbar")
-- -- --
-- local kv = skynet.call(service1,"lua","GET","a")
-- cluster.open "db"
-- cluster.open "db2"
skynet.newservice("socket1")
skynet.exit()
end)
启动服务:
./skynet ./myexample/study/config
启动 client
./3rd/lua/lua ./myexample/study/client1.lua
这时服务端收到消息 hello skynet
然后是服务器响应消息
在 socket1脚本文件的 echo中 添加 write
local function echo( id )
socket.start(id)
-- body
while true do
local str = socket.read(id)
if str then
print("server to client msg:" .. str)
socket.write(id,str)
else
socket.close(id)
end
end
end
然后在client脚本后添加代码
while true do
local str = socket.recv(fd)
if str~=nil and str~="" then
print("server to client msg :" .. str)
end
local readstr = socket.readstdin()
if readstr then
if readstr == "quit" then
socket.close(fd)
break;
else
socket.send(fd,readstr)
end
else
socket.usleep(100)
end
end
和上面一样一次运行 server 和 client 这时候客户端打印出从服务端收到的消息
参考:
官方wiki:https://github.com/cloudwu/skynet/wiki/Sproto
skynet分类api介绍 https://blog.csdn.net/lzb991435344/article/details/77216554
skynet的luaAPI https://www.jianshu.com/p/9015bb091151
skynet服务器框架:https://blog.csdn.net/linshuhe1/article/details/70174698 (超级详细 超级清晰)
风云:https://blog.codingnow.com/2014/04/skynet_snax.html
码农聚集地qq群 199678137 欢迎大佬小白加入