爲skynet移植一個lua-websocke庫

簡介

目前大部分遊戲、移動互聯網、H5客戶端主要由JavaScript、Lua、C#、C++等語言進行邏輯開發, 其主要通訊方案便是基於HTTP協議的接口請求與Websocket的推送方案.

起因

skynet內部實現了一套同步非阻塞socket庫, 並且提供了TCP通訊方案進行數據流分割. 所謂的TCP數據流分割. 就是根據一定方式讀取數據的一種流程.

最爲常見的數據分割方案應該是: 2字節頭部 + 數據載荷. 另一種通用方案是將頭部擴展爲4字節, 這樣在頭部信息中可以包含協議版本或者消息類型還可以進行平滑的進行協議升級擴展.

這些方案一般用於定製C/S網絡協議. 絕大多數場景中並沒有必須使用到這個場景, 且維護一套這樣的協議也是需要佔用開發週期的.本人也使用過國內的開發者基於skynet編寫的websockket開發庫. 就使用上來說效果不是很理想, 且期間遇到的一系列問題也需要自己實際定製化後才能解決.

剛好近期由於正在爲開發的Lua Web框架編寫Websocket使用教程, 那麼幹脆趁這個機會爲skynet移植一套專用的websocket庫.

編寫完成後, 我將它隨意的命名爲: skynet-lua-websocket.

開始移植工作

1. 握手流程

skynet要使用Websocket協議進行通訊需要實現HTTP/1.1版本中101響應方法. skyent.httpd庫可以完成HTTP協議的解析工作, 但是我們並沒有使用到它.

究其原因是因爲websocket實現交互並不複雜且所以無需依賴其它應用層協議庫的實現. HTTP本身就是一個基於文本的交互協議, 我們可以通過文本分割方案來完成它.

當連接到來時我們需要定義一個方法來處理握手協議交互(do_handshak). 在握手期間我們需要等待客戶端發送有效的HTTP請求數據(協議、方法、版本、頭部等等).

在握手期間我們不能忘記給它加上一個超時限制(set_timeout), 這個限制需要然客戶端在指定時間範圍內完成握手. 否則, 只能斷開連接來節省服務器資源開銷.

當HTTP請求數據接收完畢後, 我們需要對頭部信息進行簡單的驗證. 這個驗證過程並不會很複雜, 因爲我們只需要知道頭部信息是否完整有效即可.

在驗證完成與通過的時候, 我們需要返回一個協議升級成功的101迴應來通知客戶端, 可以使用websocket規定的協議進行通訊並且開始監聽鏈接是否有數據即可.

2. 消息交互

Websocket協議規範中定義了一些常用的消息(控制幀). 目前爲止, 我們也僅需要使用到這些消息: textbinarypingpongclose.

text/binary可以分爲一種客戶端請求消息, 它定義了客戶端發送到服務端的數據是什麼類型. 這通常在項目開發初期已經約定好傳輸協議, 所以無需過多考慮.

ping/pong通常是成對出現的; 它一般用作心跳檢查(雖然沒有人這樣做)與交互測試工作.

close一般主動推送關閉消息, 一般情況下接收到這樣的消息的處理方式爲關閉連接.

3. 事件處理

事件處理方式就仿照JavaScript設計定義了4種回調函數類型(on_openon_messageon_erroron_close), 這樣能簡化代碼編寫難度.

在每個客戶端連接到來的時候爲用戶初始化ctor方法併爲其注入ws對象用於與客戶端進行通訊(sendclose). 當客戶端連接建立完成後會在應用層觸發on_open方法, 讓開發者此時做一些相關的初始化的操作.

期間與客戶端連接保持的期間內定義了on_message方法用於接收客戶端的數據, 對需要回應的數據可以使用self.ws:send方法進行消息迴應.

最後, 我們可以在連接完成(斷開)的時候觸發on_close方法, 集中式資源回收更加簡單.

使用方法

可以通過這裏的描述學習如何使用它.

下載

項目地址在這裏.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章