以前随手写的笔记, 可能有错误, 以后再改.
一. 基本原理
一个service就是一个luavm, service之间通过skynet.call来阻塞调用, 使用skynet.send非阻塞发消息.
每个skynet.call 在被调用的service中就是一个协程, 当在协程中调用阻塞api时, 会挂起协程.
这时service还是可以对外提供服务, 于是可能产生时序问题.
例如: A, B同时call C的test服务,
function C.test(a)
print(a, "begin")
skynet.sleep(300)
print(a, "end")
end
A.call(c, test, 1)
B.call(c. test, 2)
结果:
1, begin
2, begin
1, end
2, end
此时如果服务中如果有被修改的全局变量可能会得到意外的结果也就是脏数据, 解决的办法是可以使用skynet提供的queue来保证执行的时序.
如果service中没有阻塞api, 则协程不会挂起, 此时会执行完第一个call后才会执行第二个call, 也就是没有乱序的可能, 不会产生脏数据.
- 阻塞api(相对协程而言的阻塞,也就是会挂起协程)
skynet.call, skynet.sleep, socket api
2.非阻塞api
skynet.send
二. service中的skynet.start是在创建service的调用者中同步阻塞执行
三. socket
比较坑的一点是要两次调用socket.start, 第一次相当于Accept,
第二次是让lua可以收到socket消息. 也就是向底层注册自己,告诉底层向本service发送socket消息和数据。
socket.read, socket.write都是阻塞api
tcp服务器:
id = socket.listen --监听端口
socket.start(id, accept function) -- accept function后可以把id使用skynet.send发送给另一个service,在另一个service中读写网络数据
--另一个service
socket.start(id) --这样才可以开始接收数据
socket.read -- 读数据, skynet底层已经自动缓存了recv的数据,这儿其实读的是缓冲区