赞
踩
HTTP是一种无状态协议,客户端发送请求,服务器响应,通信是单向的。这意味着服务器不能主动向客户端发送消息,而需要客户端不断轮询服务器来获取更新。
高延迟: HTTP请求-响应模式在某些情况下会导致较高的延迟,因为每次通信都需要建立连接、发送请求、等待服务器响应,然后关闭连接。
资源消耗: 对于需要实时更新的应用程序(如在线游戏、股票报价等),使用HTTP长轮询或短轮询会增加服务器负担和网络带宽消耗。
头部开销: 每个HTTP请求都需要包含头部信息,这会增加通信的开销,特别是在频繁通信的情况下。
那么怎么样才能在用户不做任何操作的情况下,网页能收到消息并发生变更。
最常见的解决方案是,网页的前端代码里不断定时发HTTP请求到服务器,服务器收到请求后给客户端响应消息。这其实时一种伪服务器推的形式。
它其实并不是服务器主动发消息到客户端,而是客户端自己不断偷偷请求服务器,只是用户无感知而已。
比如微信公众号平台,登录页面二维码出现之后,前端网页根本不知道用户扫没扫,于是不断去向后端服务器询问来确定用户是否扫码。而且是以大概1到2秒的间隔去不断发出请求,这样可以保证用户在扫码后能在1到2s内得到及时的反馈,不至于等太久。
这样有个明显的坏处就是消耗带宽,同时也会增加下游服务器的负担。
最坏情况下,用户在扫码后,需要等个1~2s,正好才触发下一次http请求,然后才跳转页面,用户会感到明显的卡顿。
我们知道,HTTP请求发出后,一般会给服务器留一定的时间做响应,比如3s,规定时间内没返回,就认为是超时。
如果我们的HTTP请求将超时设置的很大,比如30s,在这30s内只要服务器收到了扫码请求,就立马返回给客户端网页。如果超时,那就立马发起下一次请求。
这样就减少了HTTP请求的个数,并且由于大部分情况下,用户都会在某个30s的区间内做扫码操作,所以响应也是及时的。
比如百度云网盘就是这么干的。所以你会发现一扫码,手机上点个确认,电脑端网页就秒跳转,体验很好。
像这种发起一个请求,在较长时间内等待服务器响应的机制,就是所谓的长训轮机制。
以上两种本质上,其实还是客户端主动去取数据。
对于像扫码登录这样的简单场景还能用用。
但如果是网页游戏呢,游戏一般会有大量的数据需要从服务器主动推送到客户端。
现在实时性需求的应用场景越来越多。传统的 HTTP 协议在处理实时性需求方面存在很多局限,导致无法高效地支持实时通信应用。于是WebSocket 协议应运而生,通过在单个 TCP 连接上实现全双工通信,解决了传统 HTTP 协议在实时通信中的不足,成为了现代实时网络应用的基础技术之一。
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它由 IETF 于 2011 年制定,RFC 6455 标准中定义了 WebSocket 协议。与传统的 HTTP 协议不同,WebSocket 协议允许客户端和服务器之间进行实时、双向的数据传输。
WebSocket 连接的建立过程始于客户端向服务器发起的一个标准 HTTP 请求,该请求包含一个特殊的头部字段 Upgrade: websocket
,表示希望升级到 WebSocket 协议。以下是一个典型的 WebSocket 请求头示例:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
服务器收到这个请求后,会返回一个 HTTP 响应,指示同意升级到 WebSocket 协议,并包括必要的握手信息:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
上述握手过程完成后,HTTP 连接被升级为 WebSocket 连接,客户端和服务器可以通过这个连接进行双向通信。
WebSocket 数据传输采用帧(frame)的形式。每个 WebSocket 帧包含了帧的类型、长度、负载数据等信息。WebSocket 支持文本数据帧
和二进制数据帧
两种基本帧类型:
除了基本帧类型,WebSocket 还支持控制帧,如关闭帧(Close Frame)、Ping 帧和 Pong 帧。关闭帧用于终止连接,Ping 和 Pong 帧用于检测连接是否仍然活跃。
以下是一个简单的 WebSocket 数据帧结构:
0 1 2 3 4 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+
持久连接:WebSocket 通过单个持久的 TCP 连接实现客户端和服务器之间的通信,避免了频繁建立和关闭连接的开销,减少了资源消耗。
双向通信:与传统的 HTTP 请求-响应模式不同,WebSocket 允许客户端和服务器同时发送和接收数据,实现了真正的全双工通信。这对于实时性要求高的应用,如在线聊天、股票行情推送等非常重要。
低延迟:由于 WebSocket 连接一旦建立后就保持活跃状态,数据可以在客户端和服务器之间低延迟地传输,满足实时应用的需求。
减少带宽消耗:WebSocket 数据帧的头部信息比传统的 HTTP 请求要小得多,减少了带宽消耗。特别是在高频率的数据交换场景下,WebSocket 的优势更加明显。
即时通讯:WebSocket 允许即时发送和接收消息,非常适合用于在线聊天应用,如 Slack、WhatsApp Web 等。
实时数据更新:对于股票市场、体育赛事等需要实时更新数据的应用,WebSocket 可以实时推送数据更新,用户无需刷新页面即可获取最新信息。
在线游戏:在线多人游戏需要低延迟的实时通信,WebSocket 可以满足这种需求,提供流畅的游戏体验。
协同编辑:如 Google Docs 等在线协同编辑工具,通过 WebSocket 实现用户间的实时同步编辑。
物联网(IoT):在物联网应用中,设备与服务器之间需要进行实时的数据交换,WebSocket 可以提供高效的通信机制。
虽然 WebSocket 提供了高效的实时通信方式,但 HTTP/2 也通过多路复用等技术提高了 HTTP 的性能。HTTP/2 允许在单个连接上并发处理多个请求和响应,减少了延迟和资源消耗。然而,HTTP/2 依然是基于请求-响应模式,而 WebSocket 则实现了真正的全双工通信。因此,在需要实时、双向通信的场景下,WebSocket 依然是更好的选择。
WebSocket 使用 ws://
和 wss://
协议,分别对应不加密和加密的连接。wss://
使用 TLS(传输层安全性)加密,可以确保数据传输的安全性。然而,由于 WebSocket 连接一旦建立后就保持持久状态,开发者需要特别注意防止一些常见的安全漏洞,如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)。
在现代 Web 开发中,WebSocket 的实现非常简单。以下是一个使用 JavaScript 和 Node.js 实现的简单 WebSocket 服务器和客户端示例:
服务器端(Node.js):
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', ws => {
ws.on('message', message => {
console.log(`Received message => ${message}`);
ws.send(`Hello, you sent -> ${message}`);
});
ws.send('Hi there, I am a WebSocket server');
});
客户端(JavaScript):
<!DOCTYPE html> <html> <head> <title>WebSocket Example</title> </head> <body> <script> const socket = new WebSocket('ws://localhost:8080'); socket.addEventListener('open', function (event) { socket.send('Hello Server!'); }); socket.addEventListener('message', function (event) { console.log('Message from server ', event.data); }); </script> </body> </html>
在上面这个示例中,WebSocket 服务器使用 ws
模块创建,当接收到客户端消息时,会将其回显给客户端。客户端通过浏览器内置的 WebSocket API 连接到服务器,并发送和接收消息。
WebSocket 作为一种高效、实时的双向通信协议,解决了传统 HTTP 协议在实时性和效率方面的不足。它通过持久连接、低延迟和双向通信的特性,为实时网络应用提供了强大的支持。在未来,随着实时应用场景的不断增多,WebSocket 将继续发挥重要作用,为用户带来更加流畅和高效的体验。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。