GateServer閘道器伺服器(資料流切成包轉發到相應地址)

lzb991435344發表於2017-08-14

這裡寫圖片描述
1.GateServer
skynet 提供了一個通用模板 lualib/snax/gateserver.lua 來啟動一個閘道器伺服器,通過 TCP 連線和客戶端交換資料。
TCP 基於資料流,但一般我們需要以帶長度資訊的資料包的結構來做資料交換。

 gateserver:把資料流切割成包的形式轉發到可以處理它的地址。

用法:

local gateserver = require "snax.gateserver"
local handler = {}
-- register handlers here
gateserver.start(handler)
function handler.connect(fd, ipaddr)

當一個新連線建立後,connect 方法被呼叫。傳入連線的 socket fd 和新連線的 ip 地址(通常用於 log 輸出)。
(1)function handler.disconnect(fd)
當一個連線斷開,disconnect 被呼叫,fd 表示是哪個連線。

(2)function handler.error(fd, msg)
當一個連線異常(通常意味著斷開),error 被呼叫,除了 fd ,還會拿到錯誤資訊 msg(通常用於 log 輸出)。

(3)function handler.command(cmd, source, …)
讓服務處理一些 skynet 內部訊息,可以註冊 command 方法。收到 lua 協議的 skynet 訊息,會呼叫這個方法。
cmd 是訊息的第一個值,通常約定為一個字串,指明是什麼指令。
source 是訊息的來源地址。這個方法的返回值,會通過 skynet.ret/skynet.pack 返回給來源服務。
open 和 close 這兩個指令是保留的。它用於 gate 開啟監聽埠,和關閉監聽埠。
(4)function handler.open(source, conf)
如果你希望在監聽埠開啟的時候,做一些初始化操作,可以提供 open 這個方法。source 是請求來源地址,conf 是開啟 gate 服務的參數列。
(5)function handler.message(fd, msg, sz)
當一個完整的包被切分好後,message 方法被呼叫。
msg 是一個 C 指標C,需要在處理完畢後呼叫 C 方法skynet_free 釋放
sz 是一個數字,表示包的長度(C 指標指向的記憶體塊的長度)。
注意:(通常建議直接用封裝好的庫 netpack.tostring 來做這些底層的資料處理);或是通過 skynet.redirect 轉發給別的 skynet 服務處理。

(6)function handler.warning(fd, size)
當 fd 上待傳送的資料累積超過 1M 位元組後,將回撥這個方法。你也可以忽略這個訊息。
在這些方法中,還可以呼叫 gateserver 模組的方法如下:
(7)gateserver.openclient(fd) – 允許 fd 接收訊息
每次收到 handler.connect 後,你都需要呼叫 openclient 讓 fd 上的訊息進入。預設狀態下, fd 僅僅是連線上你的伺服器,但無法傳送訊息給你。這個步驟需要你顯式的呼叫是因為,或許你需要在新連線建立後,把 fd 的控制權轉交給別的服務。那麼你可以在一切準備好以後,再放行訊息。
(8)gateserver.closeclient(fd) – 關閉 fd
通常用於主動踢掉一個連線。
2.wire protocol
這裡儘可能的做最簡單的約定:
每個包就是 2 個位元組 + 資料內容。這兩個位元組是 Big-Endian 編碼的一個數字。資料內容可以是任意位元組。
所以,單個資料包最長不能超過 65535 位元組。如果業務層需要傳輸更大的資料塊,請在上層業務協議中解決。

3.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 類的訊息。

相關文章