WebSocket
WebSocket是一种在单个TCP连接上进行全双工通信的网络协议,由IETF制定为RFC 6455标准。与传统的HTTP请求-响应模式不同,WebSocket允许服务器主动向客户端推送数据,也允许客户端随时向服务器发送消息,实现真正的实时双向通信。WebSocket连接通过一次HTTP升级握手建立,之后通信双方可以在同一个持久连接上自由交换数据,无需重复建立连接,大幅降低了通信延迟和资源消耗。WebSocket广泛应用于实时聊天、在线游戏、股票行情推送、协作编辑、实时监控等需要低延迟实时通信的场景。WebSocket协议本身是文本和二进制数据的传输协议,不包含压缩功能,压缩功能通过扩展机制实现。
permessage-deflate
permessage-deflate是WebSocket协议的一个标准化扩展,定义在RFC 7692中,为WebSocket消息提供deflate压缩能力。该扩展在WebSocket握手阶段通过Sec-WebSocket-Extensions头部进行协商,服务器和客户端就压缩参数达成一致后启用。permessage-deflate支持两种压缩模式:独立压缩模式下每条消息独立压缩,上下文压缩模式下相邻消息共享压缩字典。扩展的核心优势在于能够显著减少WebSocket消息的传输大小,降低带宽消耗,特别适合传输大量结构化数据的场景。该扩展已被Chrome、Firefox、Safari、Edge等主流浏览器以及多种WebSocket服务端库广泛支持。
deflate压缩
deflate是一种广泛使用的无损数据压缩算法,结合了LZ77算法和霍夫曼编码两种技术。LZ77算法通过查找数据中的重复模式,用较短的引用替代较长的重复片段来实现压缩。霍夫曼编码则根据字符出现的频率,用较短的编码替代高频字符,用较长的编码替代低频字符,进一步减少数据表示所需的位数。deflate算法具有压缩速度快、解压速度快、压缩率适中等优点,被广泛应用于ZIP文件压缩、PNG图片压缩和HTTP内容编码等场景。在permessage-deflate扩展中,deflate算法用于压缩WebSocket消息的payload数据,平衡了压缩效果和计算开销。
压缩上下文
压缩上下文是deflate压缩算法在处理连续数据流时维护的状态信息,主要包括滑动窗口中的历史数据和对应的压缩字典。在permessage-deflate扩展的上下文压缩模式中,压缩上下文在多条消息之间共享,后续消息的压缩可以利用前序消息中出现过的数据模式。具体来说,当压缩下一条消息时,算法会在共享的滑动窗口中查找匹配的字符串片段,如果找到匹配,就可以用较短的引用来替代重复的数据,从而实现更高的压缩率。压缩上下文的存在使得数据流中的重复模式能够被跨消息利用,这是上下文压缩优于独立压缩的根本原因。压缩上下文的大小由滑动窗口参数控制。
滑动窗口
滑动窗口是deflate压缩算法中用于存储历史数据的缓冲区,大小通常为2的幂次方字节。滑动窗口的大小直接决定了压缩算法能够"记住"多远距离的历史数据。当压缩算法在当前数据中发现与窗口内历史数据匹配的片段时,可以用短引用来替代重复数据。窗口越大,查找匹配的距离越远,找到重复模式的可能性越高,压缩率通常越好。但窗口越大,需要的内存也越多,压缩和解压的计算量也会增加。在permessage-deflate扩展中,客户端和服务器各自声明自己的接收窗口大小(即愿意维护的压缩上下文大小),实际使用双方中较小的值。常见的窗口大小配置为4096字节(4KB)到32768字节(32KB)。
压缩率
压缩率是衡量压缩效果的核心指标,定义为压缩后数据大小除以原始数据大小,通常以百分比表示。压缩率越低表示压缩效果越好。例如,压缩率为百分之五十意味着压缩后的数据大小是原始数据的一半。在permessage-deflate扩展中,压缩率受到多种因素影响,包括数据的重复性、消息之间的相似度、滑动窗口大小和压缩算法的具体实现。一般来说,结构化数据如JSON和XML的压缩率通常在百分之三十到百分之七十之间,具体取决于数据内容的重复程度。文本数据的压缩率通常优于二进制数据,因为文本中的字符重复模式更容易被压缩算法捕捉。压缩率是评估是否启用permessage-deflate扩展的重要参考指标。
带宽节省
带宽节省是启用压缩后减少的网络传输数据量,计算公式为原始大小减去压缩后大小。带宽节省的百分比计算公式为(原始大小减去压缩后大小)除以原始大小再乘以百分之一百。带宽节省是评估压缩扩展实际价值的直接指标,因为网络带宽是WebSocket通信中最宝贵的资源之一。在移动网络和带宽受限的环境中,带宽节省尤为重要。permessage-deflate扩展在适当配置下可以实现百分之五十以上的带宽节省,对于数据量大的WebSocket应用场景来说,这意味着显著的传输成本降低和用户体验提升。然而,带宽节省的获得需要付出一定的CPU开销用于压缩和解压计算。
LZ77算法
LZ77算法是1977年由Abraham Lempel和Jacob Ziv提出的一种无损数据压缩算法,是deflate压缩算法的核心组成部分。LZ77的基本思想是利用数据中的重复模式进行压缩:当算法在当前位置发现与之前出现过的片段相同时,可以用一个较短的引用(距离和长度)来替代重复的数据。引用由两个参数组成:距离表示匹配片段与当前位置之间的偏移量,长度表示匹配片段的长度。LZ77算法的关键参数是滑动窗口大小,它决定了查找匹配的最大距离。窗口越大,查找匹配的范围越广,但需要的内存和计算量也越大。LZ77算法简单高效,是许多压缩格式和算法的基础。
Sec-WebSocket-Extensions
Sec-WebSocket-Extensions是WebSocket协议中用于扩展协商的HTTP头部字段。在WebSocket握手阶段,客户端通过在升级请求中包含这个头部来声明支持的扩展列表。服务器在返回的响应中也包含这个头部,从中选择双方都支持的扩展和对应的参数。对于permessage-deflate扩展,头部中包含压缩模式(client_max_window_bits、server_max_window_bits等)的参数协商信息。只有在双方都同意启用压缩并就参数达成一致后,压缩扩展才会在后续的WebSocket通信中生效。Sec-WebSocket-Extensions头部的设计体现了WebSocket协议的可扩展性,允许在不修改核心协议的情况下添加新功能。
消息帧
消息帧是WebSocket协议中数据传输的基本单位。WebSocket通信中的每条消息可以由一个或多个帧组成。每个帧包含帧头和帧载荷两部分,帧头记录了操作码、载荷长度、掩码标志等控制信息,帧载荷是实际传输的数据。对于压缩消息,帧头中还有一个压缩标志位(RSV1位)标识该帧的内容经过了deflate压缩。接收方根据这个标志决定是否需要对帧载荷进行解压处理。消息帧机制使得WebSocket能够高效地传输任意大小的数据,大消息可以分帧传输,小消息可以合并传输,灵活适应不同的应用场景。
UD5工具箱