人生处万类,知识最为贤。这篇文章主要讲述Android最佳实践——深入浅出WebSocket协议相关的知识,希望能为你提供帮助。
首先明确一下概念,
WebSocket协议是一种建立在TCP连接基础上的全双工通信的协议。概念强调了两点内容:
- TCP基础上
- 全双工通信
全双工就是指客户端和服务端可以同时进行双向通信, 强调同时、双向通信WebSocket可以应用于即时通信等场景, 比如现在直播很火热, 直播中的弹幕也可以使用WebSocket去实现。
WebSocket的协议内容可以见 The WebSocket Protocol, 讲得最全面的官方说明。简单介绍可以见维基百科WebSocket
在android客户端, 一般可以使用下面的库完成WebSocket通信
- okhttp, 一般人我不告诉他okhttp还可以用来进行WebSocket通信
- Java-WebSocket, 纯java实现的WebSocket客户端和服务端实现
先来看协议内容组成, 先上一张神图
文章图片
【Android最佳实践——深入浅出WebSocket协议】WebSocket按上面图中协议规则进行传输, 上图称为一个数据帧。
- FIN, 共1位, 标记消息是否是最后1帧, 1个消息由1个或多个数据帧构成, 若消息由1帧构成, 起始帧就是结束帧。
- RSV1, RSV2, RSV3, 各1位, 预留位, 用于自定义扩展。如果没有扩展, 各位值为0; 如果定义了扩展, 即为非0值。如果接收的帧中此处为非0, 但是扩展中却没有该值的定义, 那么关闭连接。
- OPCODE,
共4位,
帧类型,
分为控制帧和非控制帧。如果接收到未知帧,
接收端必须关闭连接。已定义的帧类型如下图所示:
文章图片
除了上图中的8, 9, 10( 0x8, 0x9, 0xA)外, 11-15(0xB-0xF)暂时没有进行定义, 为以后的控制帧保留。
消息的分片, 一般来说, 对于一个长度较小的消息, 可以使用1帧完成消息的发送, 比如说文本消息, Fin的值为1, 表示结束, Opcode值不能为0, 0表示后续还有数据帧会发送过来。
而对于一些长度较长的消息, 则需要将消息进行分片发送。比如语音消息, 这时候起始帧的FIN值为0, Opcode为非0, 接着是若干帧( FIN值都为0, Opcode值为0) , 结束帧FIN值为1, Opcode值为0。
WebSocket的控制帧有3种, 关闭帧、Ping帧、Pong帧, 关闭帧很好理解, 客户端如果收到关闭帧直接关闭连接即可, 当然客户端也可以发送关闭帧给服务器端。而Ping帧和Pong帧则是WebSocket的心跳检测, 用于保证客户端是在线的, 一般来说, 只有服务端给客户端发送Ping帧, 然后客户端发送Pong帧进行回应, 表示自己还在线, 可以进行后续通信。
- MASK, 共1位, 掩码位, 表示帧中的数据是否经过加密, 客户端发出的数据帧需要经过掩码处理, 这个值都是1。如果值是1, 那么Masking-key域的数据就是掩码秘钥, 用于解码PayloadData, 否则Masking-key长度为0。
服务器一旦收到无掩码帧, 将关闭连接。服务器可能发送一个状态码是1002( 表示协议错误) 的Close帧。
而服务器发送客户端的数据帧不做掩码处理, 一旦客户端发现经过掩码处理的帧, 将关闭连接。客户端可能使用状态码1002。
更多状态码如下图所示:
文章图片
- Payload len,
7位或者7+
16位或者7+
64位,
表示数据帧中数据大小,
这里有好几种情况。
- 如果值为0-125, 那么该值就是payload data的真实长度。
- 如果值为126, 那么该7位后面紧跟着的2个字节就是payload data的真实长度。
- 如果值为127, 那么该7位后面紧跟着的8个字节就是payload data的真实长度。
- 长度遵循一个原则, 就是用最少的字节表示长度, 举个例子, 当payload data的真实长度是124时, 在0-125之间, 必须用7位表示; 不允许将这7位表示成126或者127, 然后后面用2个字节或者8个字节表示124, 这样做就违反了原则。
- Masking-key ,
0或者4个字节,
当MASK位为1时,
4个字节,
否则0个字节。如果MASK值为1,
则发出去的数据需要经过加密处理,
加密流程如下:
推荐阅读
- Android7.0 PowerManagerService WakeLock的使用及流程
- Android JobService的使用及源码分析
- 关于使用Android新版Camera即Camera2的使用介绍 暨解决Camera.PreviewCallback和MediaRecorder无法同时进行
- Android Studio如何轻松整理字符串到string.xml中
- Android Studio 生成aar包多Module引用问题
- Android Studio 生成aar包,并在其他项目中引用
- Android Studio 生成aar包,并非debug包,而是release包
- android 调用 screenrecord 实现录屏
- Android APP使用系统签名