代码改变世界

白话skynet第一篇

2019-04-11 12:11  撞破南墙  阅读(1613)  评论(1编辑  收藏  举报

当你走过一个坐在自己店门前的杂货商面前。走过一个吸着烟斗的守门人面前,走过一个马车夫面前时,请你给我描绘一下这个杂货商、守门人和马车夫,他们的姿态,他们的外貌,要用画家那样的细节描绘出他们的精神本质,使我不至于把他们同任何别的杂货商人、任何别的守门人、任何别的马车夫混同起来,还请你只用一句话就让我知道马车夫有一匹马同其他的马是不一样的。 ——福楼拜指导莫泊桑
  从今天开始,我给自己设定了几个小目标,其中之一是:每天都写上几千字或者半个小时。今天是开始码字的第一天,坐在电脑前想了好一会,从写什么开始?目的是什么?写什么不重要,目的是培养一下码字的习惯。我的本职是码代码的。就从我了解的东西开始写吧。今天姑且为大家介绍下:Skynet。

Skynet

Skynet是一个轻量级的游戏服务器框架。语言是C+LUA。挺干净的。作者是云风。社区也一直在维护。他想做的核心的一件事情就是,提供一个消息转发机制,用C+LUA实现一个actor模式的服务器。actor模式和消息转发机制的关系是这样的,actor模式是一种设计模式,在此之前实体是通过多线程的锁等机制实现读写数据,使用actor之后,各个实体之间的沟通改为消息传递。实体本身管理自己的行为和动作。不熟悉的可能不太理解。
下面介绍下Skynet的使用。
首先Git clone源码之后,在Linux环境下编译出Skynet。
其次,他的启动方式,不是用lua编译代码跑起来,而是用编译出的Skynet带一个配置文件跑一个文件。这是一个新人觉得怪异的地方。
再说代码的编写。如上所述,这里的实体就是一个一个的服务。服务之间通过Skynet框架的消息传递。所以我们的核心任何有2个:

1.如何启动一个服务。

启动服务。 


require "skyenet"
skynet.start(function()
    ....
    skynet.newservice("服务名")
end 
)

这样算是启动了一个服务。
newservice填的服务名,他是会在config中找到对应的服务的文件,继续运行起来。

2.服务之间如何沟通。这个也是重点

2.1 首先服务需要想Skynet框架注册本服务。注册需要给什么呢?假设是你自己设计你会怎么做?每个服务需要有一个名字吧?
所以
1. 名字。作为标识。 
2. 地址(相当于邮件地址,别人给你发消息的接收地址)
3. 接收消息的语种/类型(想象一下,别人寄给你一封信,可惜你都不知道这个是什么语言写的?中文英文你知道,你分得清楚,越南文和泰文吗?我们需要提前说清楚免得别人写信的内容写
4. 消息处理
错。)
    1. 解码decode。别人的语言咱们不一定会使。咱得翻译一下。
    2. 编码encode。
    3. 来源。source。

分析处理socket的agent中的服务

1. 名字 ,  local watchdog =  skynet.newservice("服务名") 这个服务名就是标识的名字
2. 地址 , watchdog 就是地址一个int
为什么名字和地址会在外面呢。这个也可以理解。名字和地址那是对外的。是别人用来区分和标识你的。你的名字和你家的地址当然是别人(你爸和村长)取的。

skynet.register (
name = "client"  --类型名。 指示这个是客户端消息
id = skynet.PTYPE_TEXT  -- 指示skynet 数据的类型。
unpack =  ...    -- 解码
pack = ...      -- 编码方式
dispath = function (type,func)
)
... 就是

dispath 分发函数,为消息类型 type ,指定一个函数处理。
    ,function ( session , source ,  cmd ,...)   -- 内部转发,session,  来源,指令 和 其他参数
end
说到这里。我们得提到通过发消息给一个服务,调用一个服务的服务了。
skynet.call ( address, type, cmd,... )
就是说,告诉address地址的服务,有一个type类型的消息,内部约定一般服务指定服务里面哪个函数(cmd),至于参数就在...里面自动填充了

然后我们看看服务内部收到了什么,session , source ,  cmd ,... 
这里的session是指内部的一个session返回的时候调用者知道。
source是来源。
至于怎么返回,skynet.ret(skynet.pack(...))

明天继续分解这块:D
才一千三百字。