配景
我们在提出开拓跨平台组件之前, iOS 和 Android 客户端别离利用一套长毗连组件,需要双倍的人力开拓和维护;在产物需求调解上,为了在实现细节上保持一致性也具有必然的难度;Web 端与客户端长毗连的形式差异,前者利用 WebSocket,后者利用 Socket ,无形中也增加了后端的维护本钱。为了办理这些问题,我们基于 WebSocket 协议开拓了一套跨平台的长毗连组件。
架构先容
组件自上而下分为五层:
mbedTLS
实现 TLS 协议及数据加解密libuv
实现 TCP 毗连和数据的读写整体架构如下图所示:
劳务调派打点系统 t; char *host; int port; map_t params; node_init init; node_conn conn; node_write_data write_data; node_read_data read_data; node_close close; node_destroy destroy; node_reset reset; node_conn_cb conn_cb; node_write_cb write_cb; node_recv_cb recv_cb; node_close_cb close_cb;}; 在实现文件中实现接口及回调" src="/uploads/allimg/c180409/152321L540O40-14037.jpg" />
TCP 层
TCP 层我们是基于 libuv 举办开拓, libuv 是一个异步 I/O 库,而且支持了多个平台( Linux ,Windows 和 Darwin ),一开始主要应用于开拓 Node.js ,厥后逐渐在其他项目也开始利用。文件、 网络和管道 等操纵是 I/O 操纵 ,libuv 为此抽象出了相关的接口,底层利用各平台上最优的 I/O 模子实现。
它的焦点是提供了一个 event loop
,每个 event loop 包括了六个阶段:
setTimeout
、 setInterval
)的回调setImmediate()
的回调socket
的 close
事件回调劳务调派打点系统 t; char *host; int port; map_t params; node_init init; node_conn conn; node_write_data write_data; node_read_data read_data; node_close close; node_destroy destroy; node_reset reset; node_conn_cb conn_cb; node_write_cb write_cb; node_recv_cb recv_cb; node_close_cb close_cb;}; 在实现文件中实现接口及回调" src="/uploads/allimg/c180409/152321L5416160-2c28.png" />
TLS 层
mbedTLS(前身PolarSSL)是实现了一套易用的加解密算法和 SSL / TLS 库。TLS 以及前身 SSL 是传输层安详协议,给网络通信提供安详和数据完整性的保障,昆山软件开发,所以它能很好的办理数据明文和挟制改动的问题。而且其分为记录层和传输层,记录层用来确定传输层数据的封装名目,传输层则用于数据传输,而在传输之前,通信两边需要颠末握手,其包括了两边身份验证
,协商加密算法
,互换加密密钥
。
劳务调派打点系统 t; char *host; int port; map_t params; node_init init; node_conn conn; node_write_data write_data; node_read_data read_data; node_close close; node_destroy destroy; node_reset reset; node_conn_cb conn_cb; node_write_cb write_cb; node_recv_cb recv_cb; node_close_cb close_cb;}; 在实现文件中实现接口及回调" src="/uploads/allimg/c180409/152321L5422230-34Q3.png" />
Websocket 层
Websocket 层包括了对协议的实现和心跳的维护。
其最新的协议是 13 RFC 6455。协议的实现分为握手,昆山软件开发,数据发送/读取,封锁毗连。
握手要从请求头去领略。
WebSocket 首先提倡一个 HTTP 请求,在请求头加上 Upgrade
字段,该字段用于改变 HTTP 协议版本可能是换用其他协议,这里我们把 Upgrade
的值设为 websocket
,将它进级为 WebSocket 协议。
同时要留意 Sec-WebSocket-Key
字段,它由客户端生成并发给处事端,用于证明处事端吸收到的是一个可受信的毗连握手,可以辅佐处事端解除自身吸收到的由非 WebSocket 客户端提倡的毗连,该值是一串随机颠末 base64
编码的字符串。
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
收到请求后,处事端也会做一次响应:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
内里重要的是 Sec-WebSocket-Accept
,处事端通过从客户端请求头中读取 Sec-WebSocket-Key
与一串全局独一的标识字符串(俗称魔串)“258EAFA5-E914-47DA- 95CA-C5AB0DC85B11”做拼接,生生长度为160位的 SHA-1
字符串,然后举办 base64
编码,作为 Sec-WebSocket-Accept
的值回传给客户端,客户端再去理会这个值,与本身加密编码后的字符串举办较量。
处理惩罚握手 HTTP 响应理会的时候,可以用 http-paser ,理会方法也较量简朴,就是仇家书息的逐字读取再处理惩罚,详细处理惩罚你可以看一下它的状态机实现。理会完成后你需要对其内容举办理会,看返回是否正确,同时去打点你的握手状态。