爲skynet移植一個lua-websocke庫

爲skynet移植一個lua-websocke庫

簡介

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

原由

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

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

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

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

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

開始移植工做

1. 握手流程

skynet要使用Websocket協議進行通信須要實現HTTP/1.1版本中101響應方法. skyent.httpd庫能夠完成HTTP協議的解析工做, 可是咱們並無使用到它.框架

究其緣由是由於websocket實現交互並不複雜且因此無需依賴其它應用層協議庫的實現. HTTP自己就是一個基於文本的交互協議, 咱們能夠經過文本分割方案來完成它.socket

當鏈接到來時咱們須要定義一個方法來處理握手協議交互(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). 當客戶端鏈接創建完成後會在應用層觸發open方法, 讓開發者此時作一些相關的初始化的操做.

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

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

使用方法

能夠經過這裏的描述學習如何使用它.

下載

項目地址在這裏.

相關文章
相關標籤/搜索