Web端即时通讯技术:WebSocket、socket.io、SSE

      最后更新:2022-08-04 12:54:57 手机定位技术交流文章

      传统的Web端即时通讯技术从短轮询到长连询,再到Comet技术,在如此原始的HTML标准之下,为了实现所谓的“即时”通信,技术上可谓绞尽脑汁,极尽所能。

      自从发布HTML5标准以来,WebSocket技术如广泛的出现,实现了Web端即时通信技术的便利,远远领先于以前无法想象的真正的全双重实时通信,已经成为可能。

      该协议的哪个层在OSI中运行?

      应用程序层,WebSocket协议,是一个独立的基于TCP的协议。它与HTTP的唯一关系是它的手柄被HTTP服务器解释为升级请求。

      该协议运行的标准端口号码是多少?

      默认情况下,WebSocket协议使用端口80用于常规的WebSocket连接、端口443用于WebSocket连接的在传输层安全(TLS)RFC2818之上的隧道化口。

      框架的一些重要领域需要加以解释:

      1)升级:`upgrade`是HTTP1.1,用于定义转换协议的`header`域。它表示,如果服务器支持,客户端希望使用已经为此“连接”(这是TCP连接)设置的现有“网络层”,切换到另一个"应用程序层"(这里是WebSocket)协议;

      2)Connection:`Upgrade`固定字段。Connection还有其他字段,可以自己给自己科普一下;

      3)Sec-WebSocket-Key:用于发送到服务器(服务器将使用这个字段组装另一个键值,以便在手反馈消息中发送客户端);

      4)Sec-WebSocket-Protocol:识别由客户端支持的子协议的列表;

      5)Sec-WebSocket-Version:查明客户端支持的WS协议的版本列表,如果服务器不支持该版本,它必须响应它支持的版本;

      6)原产地:为防止网站间攻击的安全使用,浏览器通常使用此技术来识别原产地;

      7)Sec-WebSocket-Accept:服务器响应包含Sec-WebSocket-Key的签名值,以证明它支持请求的协议版本。

      Sec-WebSocket-Key和 Sec-WebSocket-Accept的计算方法如下:

      所有WebSockets兼容RFC 6455

      服务器使用相同的算法来计算客户挑战的答案:切换到Sec-WebSocket-Key

      内容结合的是唯一标准定义的GUI字符(258EAFA5-E914-47DA-95CA-C5AB0DC85B11),计算SHA1散射值,结果是基64编码字符串,把这个字符串发送给客户端。

      代码执行如下:

      const key = crypto.createHash('sha1')

      .update(req.headers['sec-websocket-key'] + constants.GUID, 'binary')

      .digest('base64')

      引用如下:

      Sec-WebSocket-Key/Sec-WebSocket-Accept在提供基本保护、减少恶意和意外连接方面起着关键作用。 即时通信聊天软件应用开发可以添加v:weikeyun24的建议

      作用大致归纳如下:

      1)避免服务端收到非法的websocket连接(比如http客户端不小心请求连接websocket服务,此时服务端可以直接拒绝连接);

      2)确保服务端了解网络接口连接.由于 ws 握手阶段使用 http 协议,因此,ws连接可能由 http 服务器处理并返回,客户端可以使用Sec-WebSocket-Key来确保服务端识别ws协议。(并非百分百保险,例如,总是有这样无聊的http服务器,光处理Sec-WebSocket-Key,然而,ws协议没有实现。。。);

      3)在浏览器中启动ajax请求,在设置标题时,Sec-WebSocket-Key和其他相关头条是禁止的。这阻止客户发送ajax请求,意外请求协议升级(websocket升级);

      4)这防止反向代理(不了解ws协议)返回错误的数据。例如,反向代理在连接前和连接后收到两个w连接升级请求,反向代理将第一个请求返回缓存,然后,当第二个请求到达时,直接将请求返回缓存(没有意义的返回);

      5)Sec-WebSocket-Key的主要目的不是确保数据安全,由于Sec-WebSocket-Key和Sec-WebSocket-Accept的转换公式是开放的,而且非常简单,主要作用是防止一些常见的(不意)事故。

      强调:Sec-WebSocket-Key/Sec-WebSocket-Accept的换算,只能带来基本的保障,但连接是否安全、数据是否安全、客户端/服务端是否合法的 ws客户端、ws服务端,其实并没有实际性的保证。

      各段的解释如下:

      1)FIN:1位元,用来表示这是最后一个消息断裂,当然第一个消息断裂也可以是最后一个消息断裂;

      2)RSV1, RSV2, RSV3:这些分别是1位元,如果两方之间没有自定义协议,那么这些位元的值必须为0,否则WebSocket连接必须被切断。 RSV1在w中用于表示消息是否压缩;

      3)opcode:4位,指示传输的帧类型:

      -%x0表示连续消息断裂;

      -%x1表示文本消息中断;

      -%x2表没有二进制消息断裂;

      -%x3-7操作代码为未来无法控制的消息断裂保留;

      -%x8表示连接已关闭;

      -%x9表示心脏跳动测试的 ping;

      -%xA指作心脏跳动测试的拍子;

      - %xB-F 保留操作代码,用于未来控制消息中断。

      4)Mask: 1 bit。定义传输的数据是否有加掩码,如果设置为1,掩码键必须放在masking-key区域,客户端发送给服务端的所有消息,此位都是1;

      5)Payload length:传输数据的长度,它以括号的形式表示: 7, 7+16, 7+64。如果这个值以字节表示为0-125的范围,然后这个值代表传输数据的长度;如果这个值是126,接下来的两个字符代表一个16位不签名的数字,用于指示传输数据的长度;如果此值为127,则以下为由8字节表示的64位不符号,这个数字用于指示传输数据的长度。多字节长度的数目按网络字节的顺序表示。载入的数据长度是扩展数据和应用数据的总数,扩展数据的长度可能为0,因此负载数据的长度是应用程序数据的长度。

      6) Masking-key:0或4字节,客户端发送到服务端的数据由嵌入32位值编码;加密密钥只有在加密位设置为1时才会存在;

      7)Extension data: x位,如果客户与服务终止之间没有特别协议,所以扩展数据的长度总是0,任何扩展必须指定扩展数据的长度,或计算长度的方法,如何确定握手的正确方法。如果存在扩展数据,然后扩展的数据将包含在载入数据的长度之内;

      8)应用程序数据:y-bit,任何应用程序数据,放置在扩展数据之后,应用程序数据的长度=负载数据的长度-扩展数据的长度;

      9)负载数据:(x+y)位数,负载数据是扩展数据和应用程序数据长度的总数;

      对上述各领域的介绍,有一个Mack需要说些什么。

      masking-key是一个由客户端选择的随机32位数。 加密操作不会影响数据负载的长度。

      下面的算法用于加密和反加密操作。

      首先,假设:

      1)original-octet-i:原始数据的第一个字符;

      2)变换-octet-i:转换后的数据的第一个字符;

      3)j:i模4的结果;

      4) masking-key-octet-j:用于 masking key node j。

      该算法被描述为: original-octet-i与 masking-key-octet-j不同,然后转换为-octet-i。

      即:j = i MOD 4 transformed-octet-i = original-octet-i XOR masking-key-octet-j

      我要指出的重点是:

      在WebSocket协议中,数据加密用于增强协议安全性,但数据加密并不是为了保护数据本身,因为算法本身是开放的,操作并不复杂。 除了加密通道本身,似乎没有许多有效的方法来保护通信安全。

      因此,为什么引入加密计算,除了增加计算机上的计算量外,似乎没有很多好处(这也是许多学生的问题)。

      答案还是两个字: 安全。但并不是为了防止数据泄密,而是为了防止早期版本的协议中存在的代理缓存污染攻击(proxy cache poisoning attacks)等问题。

      传统的网络长连接技术实现背景

      在真正的Web端产品中,并非所有Web客户端都支持长距离连接,换句话说,在WebSocket协议发布之前,有三个实现WebSocket-like功能的方法。

      这三种方式是:

      1)Flash:使用Flash是一种简单的方法。不过很明显的缺点就是Flash并不会安装在所有客户端上,比如iPhone/iPad。

      2)Long-Polling:也就是众所周之的“长轮询”,在过去,这是一种有效的技术,但并没有对消息发送进行优化。虽然我不会把AJAX长轮询当做一种hack技术,但它确实不是一个最优方法;

      3)Comet:在过去,这被称为Web端的“服务器推”技术,相对于传统的 Web 应用, 开发 Comet 应用具有一定的挑战性,

      那么如果单纯地使用WebSocket的话,那些不支持的客户端怎么办呢?难道直接放弃掉?

      当然不是。Guillermo Rauch大神写了socket.io这个库,对WebSocket进行封装,从而让长连接满足所有的场景,不过当然得配合使用对应的客户端代码。

      socket.io将使用特征检测方法决定是否使用Websocket/ajax long query/flash等来建立连接。

      那么socket.io是如何做到这些的呢?

      我们以下列问题来学习:

      插座. io的新特性是什么?

      插座. io如何实现特征检测?

      插座.我有什么洞?

      插座. io的实际应用是什么,应该注意什么?

      如果孩子对上述问题的认识很清楚,就不需要再读一遍。

      通过前面的章节,读者熟悉WebSocket和Socket的功能。 基于此, io与WebSocket相比有什么新之处?

      socket.io实际上有一套包含Websocket的协议,称为Engine。 io协议实现了一个基本的双向通信引擎 Engine.io。

      而socket.io则是建立在engine.io上的一个应用层框架而已。所以我们研究的重点便是engine.io协议。

      在 socket.io的REDME中提到了它的实现的一些新功能(回答问题1):

      1)可靠性:即使应用程序环境存在,仍可建立连接:代理或负载平衡设备个人防火墙或防病毒软件;

      2)支持自动连接:除非具体指定,未连接的客户端将重新连接到服务器,直到服务器恢复到可用性;

      (三)断电检测:在发动机内,叶层实现心脏跳动机制,这允许客户端和服务器知道其中一个不能响应。该函数通过在服务端和客户端设置计时器来实现,在连接握手的时候,服务器将通知客户心跳的间隔时间和加班时间;

      4)二进制支持:任何序列化数据结构都可以用于发送;

      5)跨浏览器支持:图书馆甚至支持IE8;

      6)支持复用:为了在应用程序中将创建的关注点隔离开来,Socket.io允许你创建多个namespace,这些namespace拥有单独的通信通道,但将共享相同的底层连接;

      7)支持房间:在每个命名空间下,您可以定义任何数量的频道,我们称之为“房间”,您可以添加或离开一个房间,甚至广播消息到指定的房间。

      注:Socket.IO不是WebSocket实现,虽然 Socket.IO确实在可能的情况下会去使用WebSocket作为一个transport,但是它增加了许多元数据到每个报告:报告的类型和命名空间和AckID。这就是标准的Web Socket客户端无法成功地连接到Socket.IO服务器的原因,同样的接口。IO客户端也无法连接到标准的WebSocket服务器。

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/31526.html

          热门文章

          文章分类