GateServer 网关

skynet提供了一个通用模板lualib/snax/gateserver.lua来启动一个网关服务器,通过TCP连接和客户端交换数据.


TCP 基于数据流,但一般我们需要以带长度信息的数据包的结构来做数据交换,gateserver做的就是这个工作,把数据流切割成包的心事转发到可以处理它的地址


用法

ocal gateserver = require "snax.gateserver"

local handler = {}

-- register handlers here

gateserver.start(handler)

这样就可以启动一个网关服务,handler是一组自定义的消息处理函数,分别有:

function handler.connect(fd, ipaddr)
当一个新连接建立后,connect方法被调用,传入连接的socket fd 和新连接的ip地址(通常用于log输出)


function handler.disconnect(fd)
当一个连接断开,disconnect被调用,fd表示是哪个连接.

function handler.error(fd, msg)

当一个连接异常(通常意味着断开),error被调用,除了fd,还会拿到错误信息msg(通常用于log输出)

function handler.command(cmd, source, ...)
如果你希望让服务处理一些skynet内部消息,可以注册command方法,收到Lua协议的skynet消息,会调用这个方法,cmd是消息的第一个值,通常约定为一个字符串,指明是什么指令,source是消息的来源地址.这个方法的返回值,会通过skynet.ret/skynet.oack返回给来源服务.


open 和 close 这两个指令是保留的,它用于gate打开监听端口,和关闭监听端口.

function handler.open(source, conf)
如果你希望在监听端口打开的时候,做一些初始化操作,可以提供open这个方法,source是请求来源地址,conf是开启gate的参数表.


function handler.message(fd, msg, sz)

当一个完整的包被却分好后,message方法被调用,这里msg是一个C指针,sz是一个数字,表示包的长度(C指针指向的内存块的长度),注意:这个C指针需要在处理完毕后调用C方法skynet_free释放.(通常建议直接用封装好的库netpack.tostring来做这些底层的数据处理);或是通过skynet.redirect转发给别的skynet服务处理.

function handler.warning(fd, size)

当fd上待发送的数据累计超过1M字节后,将回调这个方法,你也可以忽略这个消息.

在这些方法中,还可以调用gateserver模块的方法如下.

gateserver.openclient(fd)   -- 允许 fd 接收消息
每次收到handler.connect后,你都需要调用openclient让fd上的消息进入.默认状态下,fd仅仅是连接上你的服务器,但无法发送消息给你,这个步骤需要你显示的调用时因为,回叙你需要在新连接建立后,把fd的控制权转交给别的服务,那么你可以在一切准备好以后,再放心消息.

gateserver.closeclient(fd) -- 关闭 fd
通常用于主动踢掉一个连接.


wire protocol

这里尽可能的座最简单的约定

每个包就是2个字节+数据内容,这两个字节是big-endian编码的一个数字,数据内容可以是任意字节.

所以,单个数据包最长不能超过65535字节,如果业务层需要传输更大的数据块,请在上层业务协议中解决.


netpack api

lualib-src/lua-netpack.c 是处理这类数据包的库

local netpack = require "netpack"
可以加载这个库

netpack.pack(msg.[sz]) 把一个字符串(或一个C指针加一个长度)打包成带2字节包头的数据块,这个api返回一个lightuserdata和一个number.你可以直接送到socket.write发送(socket.write负责最终释放内存).


netpack.tostring(msg,sz) 把handler.message 方法收到的msg.sz转换成一个lua string ,并释放msg占用的C内存.


netpack 还有一些内部api用于gateserver的实现.


Gate 服务器

service/gate.lua 是一个实现完整的网关服务器,同时也可以作为snax.gateserver的使用范例.examples/watchdog.lua是一个可以参考的例子,它启动了一个service/gate.lua服务,并将处理外部的连接的消息转发处理.


gate服务启动后,并非立刻开始监听,要让gate服务器开启监听端口,可以通过lua协议向它发送一个open指令,附带一个启动参数表,下面是一个示范:


skynet.call(gate, "lua", "open", {
    address = "127.0.0.1", -- 监听地址 127.0.0.1
    port = 8888,    -- 监听端口 8888
    maxclient = 1024,   -- 最多允许 1024 个外部连接同时建立
    nodelay = true,     -- 给外部连接设置  TCP_NODELAY 属性
})

注: 这个模板不可以和Socket库一起使用,因为这个模板接管了socket类的消息.

其它方案

skynet并不限制你怎样编写网关,比如你还可以使用这个模块:http://blog.codingnow.com/2016/03/skynet_tcp_package.html

你可能感兴趣的:(skynet)