欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

以日志插件为例: 增加日志文件 在头文件中定义  zim_log_s  结构体(这里没有额外的成员): typedef

点击: 次  来源:昆山软开发 时间:2018-04-09

原文出处: 宫城

配景

我们在提出开拓跨平台组件之前, iOS 和 Android 客户端别离利用一套长毗连组件,需要双倍的人力开拓和维护;在产物需求调解上,为了在实现细节上保持一致性也具有必然的难度;Web 端与客户端长毗连的形式差异,前者利用 WebSocket,后者利用 Socket ,无形中也增加了后端的维护本钱。为了办理这些问题,我们基于 WebSocket 协议开拓了一套跨平台的长毗连组件。

架构先容

组件自上而下分为五层:

  • Native 层:认真业务请求封装和数据理会,与原生举办交互
  • Chat 层:认真提供底层通信利用的 c 接口,包括毗连、读写和封锁
  • Websocket 层:实现 websocket 协议及维护心跳
  • TLS 层 :基于 mbedTLS 实现 TLS 协议及数据加解密
  • TCP 层:基于 libuv 实现 TCP 毗连和数据的读写
  • 整体架构如下图所示:

    以日志插件为例: 增加日志文件 在头文件中界说  zim_log_s  布局体(这里没有特另外成员): typedef struct zim_log_s zim_log_t;struct zim_log_s { dul_node_t *pre; dul_node_t *nex  <a href=劳务调派打点系统 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 包括了六个阶段:

  • timers 阶段:这个阶段执行 timer( setTimeout 、 setInterval )的回调
  • I/O callbacks 阶段:执行一些系统挪用错误,好比网络通信的错误回调
  • idle , prepare 阶段:仅 node 内部利用
  • poll 阶段:获取新的 I/O 事件, 适当的条件下 node 将阻塞在这里
  • check 阶段:执行 setImmediate() 的回调
  • close callbacks 阶段:执行 socket 的 close 事件回调
  • 以日志插件为例: 增加日志文件 在头文件中界说  zim_log_s  布局体(这里没有特另外成员): typedef struct zim_log_s zim_log_t;struct zim_log_s { dul_node_t *pre; dul_node_t *nex  <a href=劳务调派打点系统 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 是传输层安详协议,给网络通信提供安详和数据完整性的保障,昆山软件开发,所以它能很好的办理数据明文和挟制改动的问题。而且其分为记录层和传输层,记录层用来确定传输层数据的封装名目,传输层则用于数据传输,而在传输之前,通信两边需要颠末握手,其包括了两边身份验证协商加密算法互换加密密钥

    以日志插件为例: 增加日志文件 在头文件中界说  zim_log_s  布局体(这里没有特另外成员): typedef struct zim_log_s zim_log_t;struct zim_log_s { dul_node_t *pre; dul_node_t *nex  <a href=劳务调派打点系统 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 ,理会方法也较量简朴,就是仇家书息的逐字读取再处理惩罚,详细处理惩罚你可以看一下它的状态机实现。理会完成后你需要对其内容举办理会,看返回是否正确,同时去打点你的握手状态。

    数据发送/读取