国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

造輪子系列(二): 史上最簡單的長連接通信協議及實現

Alliot / 1959人閱讀

摘要:背景現在寫客戶端或者網頁的時候越來越多的需要與長連接打交道尤其是在這個老板動不動就要搞一個聊天系統的時代后端大哥們于是分分鐘就能造一個基于或者的消息協議出來但是問題在于每做一個新項目后端大哥們就能造出一個新協議而且能有各種神奇的限制比如說要

背景

現在寫客戶端或者網頁的時候, 越來越多的需要與長連接打交道, 尤其是在這個老板動不動就要搞一個聊天系統的時代, 后端大哥們于是分分鐘就能造一個基于TCP或者WebSockets的消息協議出來. 但是問題在于每做一個新項目, 后端大哥們就能造出一個新協議, 而且能有各種神奇的限制. 比如說要在長連接當中保持一個狀態機, 發送某條消息后收到的下一條消息一定是XXX, 或者完全一個JSON就直接丟了出來等等. 雖然都能用, 但是卻需要在各種地方維護著不同的底層通信庫, 沒有章法可依, 所以草擬了這個協議.

目前最熱門的消息協議莫過于MQTT和gRPC了, 前者被定義為A lightweight messaging protocol for small sensors and mobile devices, optimized for high-latency or unreliable networks, 即一個為傳感器和移動設備定制的消息協議. 最大的特點莫過于其固定消息頭只有2字節, 以及QoS服務質量控制了. 對于前者, 無可厚非, 任何一個長連接的消息協議都應該可以做到如此, 甚至更簡單(STMP便是如此), 其次其QoS設計使得通信層面就變得很復雜, 使得其更像一個消息隊列協議, 而不是簡單的通信協議. 而gRPC則是一個基于ProtocolBuffers發展起來的RPC協議以實現. 集成度很高, 底層基于HTTP 2, 所以通用性很好, 如果是做大項目并且團隊有一定的技術/運維積累的話, 是非常推薦的選擇, 但是這和STMP不沖突, STMP面向的是對協議健壯性要求不高, 只需要一個能用的規范的企業/團隊中, 你可以用在Web端, 也可以用在客戶端, 或者智能家居等嵌入式設備中, 反觀gRPC, 則顯得過于龐雜.

簡介

協議取名STMP, 意思是最簡單的消息協議(The simplest message protocol). 項目托管在GitHub上, 包含了完整的協議文檔以及相關實現, 詳細了解請移步GitHub, 同時歡迎提交PR/Issue, 地址是https://github.com/acrazing/stmp.

簡單來說, STMP有以下特點:

非常精簡的固定頭部, 僅有一字節(二進制序列化)

支持二進制序列化(TCP)以及文本序列化(WebSockets), 文本序列化支持消息分包傳送(傳遞二進制數據)

與IP協議掩碼類似的上層路由控制

負載編碼格式對協議透明

心跳檢測

四種消息類型: 心跳, 請求, 通知, 回復

與HTTP協議類似的返回狀態碼控制

消息字段定義

一個全雙工的通信系統中, 雙端需要有效識別對方發來的消息, 并作出相應的處理, 選擇是否回應等操作, 所以除了實際的負載之外, 還需要若干標志字段. STMP中, 完整的消息字段列表如下, 需要注意的是并不是每條消息都會包含所有的這些字段, 需要根據網絡環境以及消息類型確定應該包含的字段列表. 但是如果某條消息包含了以下這些字段中的某一些字段的話,排序順序一定與字段在下面出現的順序相同.

消息類型(KIND): 表示一條消息的類型, 可能的取值有:

0: 心跳消息(Ping Message)

1: 請求消息(Request Message)

2: 通知消息(Notify Message)

3: 回復消息(Response Message)

消息編碼格式(ENCODING): 表示負載的編碼格式, 上層應用/編解碼層收到消息后, 可以通過此字段對負載進行解碼操作, 由于頭部長度限制, 可能的取值范圍為0-7, 已經約定的編碼格式如下:

0: 保留格式, 表示不包含負載, 此時消息中一定不存在PS以及PAYLOAD字段

1: Protocol Buffers, 參考 Protocol Buffers

2: JSON, 參考 JSON

3: MessagePack, 參考 MessagePack

4: BSON, 參考 BSON

5: 原始二進制數據

消息ID(ID): 消息的臨時ID, 取值范圍為0x0000-0xFFFF, 用于請求與回復消息當中, 請求方應該保證在超時的時限內此ID唯一, 回復方在回復時帶上此ID以供發送方識別

消息請求動作(ACTION): 請求的動作, 用于上層應用進行路由控制, 取值范圍為0x00000000-0xFFFFFFFF, 即32位整型, 上層應用中可以寫成xxx.xxx.xxx.xxx的形式, 與IP類似. 接收方在收到相應的動作后必需能夠正確識別, 并轉交給相應的處理器進行處理. 其中0x00-0xFF為保留動作, 用于協議內部使用. 目前已使用的動作有:

0x00: 版本協商(Check Versions)

狀態碼(STATUS): 處理結果狀態碼, 用在回復消息中, 表明對請求的處理結果, 取值范圍為0x00-0xFF, 其中0x00-0x7F為保留取值, 含義與ACTION無關, 0x80-0xFF為用戶定義的狀態值, 含義根據ACTION不同有可能不同. 目前已定義的狀態碼有(和HTTP類似, 只不過換了個值而已):

0x00: Ok, 200

0x10: MovedPermanently, 301

0x11: Found, 302

0x12: NotModified, 304

0x20: BadRequest, 400

0x21: Unauthorized, 401

0x22: PaymentRequired, 402

0x23: Forbidden, 403

0x24: NotFound, 404

0x25: RequestTimeout, 408

0x26: RequestEntityTooLarge, 413

0x27: TooManyRequests, 429

0x30: InternalServerError, 500

0x31: NotImplemented, 501

0x32: BadGateway, 502

0x33: ServiceUnavailable, 503

0x34: GatewayTimeout, 504

0x35: VersionNotSupported, 505

負載長度(PS): 表示PAYLOAD的長度, 以字節為單位, 取值范圍為0x00000000-0xFFFFFFFF, 即負載最大長度為4Gb, 此字段存在與否由網絡環境與ENCODING決定, 如果ENCODING0, 或者網絡環境能夠正確的分包(比如WebSockets環境), 則一定不存在此字段, 否則一定存在此字段.

負載(PAYLOAD): 實際的負載, 長度由PS或者網絡分包結果確定, 編碼方式由ENCODING決定, 協議本身不負責負載的編解碼, 需要交由上層的應用進行解釋.

消息類型

如前所述, STMP中消息分類四種類型, 不同的消息類型可能包含的字段及含義有所不同, 詳細如下:

心跳消息

雙端為了保證對方連接有效性, 必需定期發送一個心跳消息給對方, 此消息一定不包含任何除了KIND外的其它任何字段. 同時此消息不需要 回復, 如果一方在約定的時間內沒有收到對方發送的心跳消息, 則表明對方已經斷開連接或者出現異常, 應該立即斷開連接.

請求消息

此消息表示發送方請求接收方返回某一個資源, 如果在指定的時間內未收到接收方的回復, 則放棄等待, 并向上層應用返回一個STATUS0x25的回復, 表示請求超時.
此消息一定包含KIND, ENCODING, ID, ACTION字段, 可能包含PS, PAYLOAD字段, 一定不包含STATUS字段.

通知消息

此消息表示發送方向接收方發送一個通知, 接收方無需回復此消息.

此消息一定包含KIND, ENCODING, ACTION字段, 可能包含PS, PAYLOAD字段, 一定不包含ID, STATUS字段.

回復消息

此消息表示發送方向接收方發送一個回復消息以回復對方曾經發送的某一條請求消息, 此消息的ID為接收方發送的此條請求消息ID. 如果上層應用在指定的時間內未返回消息, 則向發送方發送一個STATUS0x34的回復消息, 表明上層應用處理超時.

此消息一定包含KIND, ENCODING, ID, STATUS字段, 可能包含PS, PAYLOAD字段, 一定不包含ACTION字段.

消息序列化

針對不同的網絡環境, 協議制定了兩套不同的序列化方式以應對, 主要原因是瀏覽器環境中將字符串轉換成ArrayBuffer再通過WebSockets發送性能實在無法直視(實現方式可以參考stmp/impl/js/stmp/text.ts, 主要是將UTF-16編碼和字符串轉換成UTF-8的Uint8Array), 同時為了更好的Web端調試, 所以制定了一套文本序列化方案.

二進制序列化

二進制序列化中, 固定頭部占一個字節, 包含KIND以及ENCODING字段, 如果KIND0, 則ENOCDING也必需為0, 表示一個心跳消息. 完整的結構如下:

|   0 ... 7   |  8 ... 15  |  16 ... 23  |  24 ... 31  |
| FixedHeader |           ID             |    ACTION   |
|               ACTION                   |    STATUS   |
|                         PS                           |
|                 PAYLOAD    ...                       |

其中的多字節字段, 包括ID, ACTION, PS字段, 如果存在的話, 一定BigEndian的方式傳遞. 此外, 固定頭部如下:

|   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7   |
|     KIND      |       ENCODING        |   0   |   0   |   0   |

最后三個位為保留位(未用到), 全部置零.

文本就序列化

所有的字段通過字符|連接, 即:

KIND(1)|ENCODING(1)|ID?(1-5)|ACTION?(1-10)|STATUS?(1-3)|PS?(1-10)|PAYLOAD?(...)

消息分割, 在使用文本序列化方式傳遞二進制數據時, 瀏覽器環境不能高效的將二者混雜在一起, 所以允許分成兩個包進行傳送, 前者傳遞頭部信息, 后者傳遞實際的二進制PAYLOAD, 此時ENCODING一定不0, 同時, PAYLOAD在頭部包中不存在. WebSockets自身保證了包的有序性.

對于一個心跳消息, 只有一個KIND字段, 所以其結果一定為"0".

區分文本消息與二進制消息

這是比較有趣的地方, 文本消息和二進制消息可以通過首字節完全區別開來: 對于文本消息, 首字節為"0", "1", "2", "3"中的一個, 即0x30-0x33, 而對于二進制消息, 要么為0x00(心跳消息), 要么大于或者等于0x40, 因為KIND不為0時其值一定大于0b01000000.

版本協商

協議版本有兩個字段, 分別為MAJORMINOR, 二者取值范圍均為015, 即0x00xF, 可以序列化為MAJOR.MINOR的形式.

當前協議版本為0.1.

客戶端在發起連接成功后, 需要發送一個ACTION為0x00的消息給服務端, 消息ID必需為0, 負載編碼方式為Raw, 負載為客戶端可接受的版本號
列表. 服務端在收到此消息后, 如果可以處理客戶端發送過來的版本列表中的某一個, 則回復一個STATUS為Ok的回復消息, 負載為所選擇的協議版本
號, 如果不能處理, 則返回一個VersionNotSupported錯誤消息, 負載為空, 并且關閉連接.

版本號序列化

在二進制消息中, 一個版本號序列化為1字節長度的信息, 其中前4位為MAJOR, 后4位為MINOR值. 多個版本號直接連接在一起. 在文本消息中, 一個版本號序列化為2字節長度的信息, 其中前1字節為MAJOR, 后1字節為MINOR值, 多個版本號直接相連.

實現

目前僅實現了Golang和JS的簡單的消息編解碼部分, 地址在: go版本, js版本, 還有很多工作要做T_T, 如果有人提PR就好了?????.

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84446.html

相關文章

  • Android OkHttp 上最優雅的設置baseUrl

    前言 RxHttp截止本文發表已經推廣了4個禮拜,目前已經有了141個star,如下: showImg(https://user-gold-cdn.xitu.io/2019/5/20/16ad5f3b6d10d9be); 其中一文,Android 史上最優雅的實現文件上傳、下載及進度的監聽更是得到了大神劉皇叔微信公眾號的推送,歡迎讀者關注劉皇叔微信公眾號「劉望舒」,每天都有精彩的文章推送,真的很棒...

    番茄西紅柿 評論0 收藏0
  • 架構~微服務

    摘要:接下來繼續介紹三種架構模式,分別是查詢分離模式微服務模式多級緩存模式。分布式應用程序可以基于實現諸如數據發布訂閱負載均衡命名服務分布式協調通知集群管理選舉分布式鎖和分布式隊列等功能。 SpringCloud 分布式配置 SpringCloud 分布式配置 史上最簡單的 SpringCloud 教程 | 第九篇: 服務鏈路追蹤 (Spring Cloud Sleuth) 史上最簡單的 S...

    xinhaip 評論0 收藏0
  • 【大量干貨】上最完整的Tengine HTTPS原理解析、實踐與調試

    摘要:內容主要有四個方面趨勢基礎實踐調試。一趨勢這一章節主要介紹近幾年和未來的趨勢,包括兩大瀏覽器和對的態度,以及淘寶天貓和阿里云的實踐情況。完整性是指為了避免網絡中傳輸的數據被非法篡改,使用算法來保證消息的完整性。 摘要: 本文邀請阿里云CDN HTTPS技術專家金九,分享Tengine的一些HTTPS實踐經驗。內容主要有四個方面:HTTPS趨勢、HTTPS基礎、HTTPS實踐、HTTPS...

    snowell 評論0 收藏0
  • 即時通信相關技術總結

    摘要:解決問題即時通信要解決三方面的問題雙全工通信低延時支持跨域各種即時通信技術輪詢客戶端定時向服務器發送請求,服務器接到請求后馬上返回響應信息并關閉連接。優點實現真正的即時通信,而不是偽即時。 解決問題 即時通信要解決三方面的問題: 雙全工通信 低延時 支持跨域 各種即時通信技術 輪詢 客戶端定時向服務器發送Ajax請求,服務器接到請求后馬上返回響應信息并關閉連接。優點:后端程序編寫比...

    reclay 評論0 收藏0

發表評論

0條評論

Alliot

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<