WebSocket介绍+3分钟时间使用WebSocket搭建属自己的聊天室

WebSocket 的由来

  • 在 WebSocket 出现之前,我们想实现实时通信、变更推送、服务端消息推送功能,我们一般的方案是使用 Ajax 短轮询、长轮询两种方式:
  • 比如我们想实现一个服务端数据变更时,立即通知客户端功能,没有 WebSocket 之前我们可能会采用以下两种方案:短轮询或长轮询

短轮询、长轮询(来源:即时通讯网)

  • 上面两种方案都有比较明显的缺点:
1、HTTP 协议包含的较长的请求头,有效数据只占很少一部分,浪费带宽
2、短轮询频繁轮询对服务器压力较大,即使使用长轮询方案,客户端较多时仍会对客户端造成不小压力
  • 在这种情况下,HTML5 定义了 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket 是什么

  • WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。
  • WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。客户端和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

短轮询和WebSocket的区别(来源:即时通讯网)

WebSocket 优缺点

优点

  • 实时性: WebSocket 提供了双向通信,服务器可以主动向客户端推送数据,实现实时性非常高,适用于实时聊天、在线协作等应用。
  • 减少网络延迟: 与轮询和长轮询相比,WebSocket 可以显著减少网络延迟,因为不需要在每个请求之间建立和关闭连接。
  • 较小的数据传输开销: WebSocket 的数据帧相比于 HTTP 请求报文较小,减少了在每个请求中传输的开销,特别适用于需要频繁通信的应用。
  • 较低的服务器资源占用: 由于 WebSocket 的长连接特性,服务器可以处理更多的并发连接,相较于短连接有更低的资源占用。
  • 跨域通信: 与一些其他跨域通信方法相比,WebSocket 更容易实现跨域通信。

缺点

  • 连接状态保持: 长时间保持连接可能会导致服务器和客户端都需要维护连接状态,可能增加一些负担。
  • 不适用于所有场景: 对于一些请求-响应模式较为简单的场景,WebSocket 的实时特性可能并不是必要的,使用 HTTP 请求可能更为合适。
  • 复杂性: 与传统的 HTTP 请求相比,WebSocket 的实现和管理可能稍显复杂,尤其是在处理连接状态、异常等方面。

WebSocket 适用场景

  • 实时聊天应用: WebSocket 是实现实时聊天室、即时通讯应用的理想选择,因为它能够提供低延迟和高实时性。
  • 在线协作和协同编辑: 对于需要多用户协同工作的应用,如协同编辑文档或绘图,WebSocket 的实时性使得用户能够看到其他用户的操作。
  • 实时数据展示: 对于需要实时展示数据变化的应用,例如股票行情、实时监控系统等,WebSocket 提供了一种高效的通信方式。
  • 在线游戏: 在线游戏通常需要快速、实时的通信,WebSocket 能够提供低延迟和高并发的通信能力。
  • 推送服务: 用于实现消息推送服务,向客户端主动推送更新或通知。

主流浏览器对 WebSocket 的兼容性

主流浏览器对 WebSocket 的兼容性

  • 由上图可知:目前主流的 Web 浏览器都支持 WebSocket,因此我们可以在大多数项目中放心地使用它。

WebSocket 通信过程以及原理

建立连接

  • WebSocket 协议属于应用层协议,依赖传输层的 TCP 协议。它通过 HTTP/1.1 协议的 101 状态码进行握手建立连接。

具体过程

  • 客户端发送一个 HTTP GET 请求到服务器,请求的路径是 WebSocket 的路径(类似 ws://http://example.com/socket)。请求中包含一些特殊的头字段,如 Upgrade: websocket 和 Connection: Upgrade,以表明客户端希望升级连接为 WebSocket。
  • 服务器收到这个请求后,会返回一个 HTTP 101 状态码(协议切换协议)。同样在响应头中包含 Upgrade: websocket 和 Connection: Upgrade,以及一些其他的 WebSocket 特定的头字段,例如 Sec-WebSocket-Accept,用于验证握手的合法性。
  • 客户端和服务器之间的连接从普通的 HTTP 连接升级为 WebSocket 连接。之后,客户端和服务器之间的通信就变成了 WebSocket 帧的传输,而不再是普通的 HTTP 请求和响应。

示例

// 客户端请求
GET ws://localhost:8888/ HTTP/1.1
Host: localhost:8888
Connection: Upgrade
Upgrade: websocket
Origin: http://localhost:63342
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7
Sec-WebSocket-Key: b7wpWuB9MCzOeQZg2O/yPg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits// 服务端响应
HTTP/1.1 101 Web Socket Protocol Handshake
Connection: Upgrade
Date: Wed, 22 Nov 2023 08:15:00 GMT
Sec-WebSocket-Accept: Q4TEk+qOgJsKy7gedijA5AuUVIw=
Server: TooTallNate Java-WebSocket
Upgrade: websocket

Sec-WebSocket-Key

  • 与服务端响应头部的 Sec-WebSocket-Accept 是配套的,提供基本的防护,比如恶意的连接,或者无意的连接;这里的“配套”指的是:Sec-WebSocket-Accept 是根据请求头部的 Sec-WebSocket-Key 计算而来,计算过程大致为基于 SHA1 算法得到摘要并转成 base64 字符串。

Sec-WebSocket-Extensions

  • 用于协商本次连接要使用的 WebSocket 扩展。

数据通信

  • WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧并将关联的帧重新组装成完整的消息。

数据帧

      0                   1                   2                   30 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 ...                |+---------------------------------------------------------------+

帧头(Frame Header)

  • FIN(1比特): 表示这是消息的最后一个帧。如果消息分成多个帧,FIN 位在最后一个帧上设置为 1。
  • RSV1、RSV2、RSV3(各1比特): 保留位,用于将来的扩展。
  • Opcode(4比特): 指定帧的类型,如文本帧、二进制帧、连接关闭等。
WebSocket 定义了几种帧类型,其中最常见的是文本帧(Opcode 为 0x1)和二进制帧(Opcode 为 0x2)。其他帧类型包括连接关闭帧、Ping 帧、Pong 帧等。
  • Mask(1比特): 指示是否使用掩码对负载进行掩码操作。
  • Payload Length: 指定数据的长度。如果小于 126 字节,直接表示数据的长度。如果等于 126 字节,后面跟着 16 比特的无符号整数表示数据的长度。如果等于 127 字节,后面跟着 64 比特的无符号整数表示数据的长度。

掩码(Masking)

  • 如果 Mask 位被设置为 1,则帧头后面的 4 字节即为掩码,用于对负载数据进行简单的异或操作,以提高安全性。

负载数据(Payload Data)

  • 实际要传输的数据,可以是文本、二进制数据等

来自 MDN 的一个小例子

Client: FIN=1, opcode=0x1, msg="hello"
Server: (process complete message immediately) Hi.Client: FIN=0, opcode=0x1, msg="and a"
Server: (listening, newmessage containing text started)Client: FIN=0, opcode=0x0, msg="happy new"
Server: (listening, payload concatenated to previous message)Client: FIN=1, opcode=0x0, msg="year!"
Server: (process complete message) Happy new year to you too!

维持连接

  • 当建立连接后,连接可能因为网络等原因断开,我们可以使用心跳的方式定时检测连接状态。若连接断开,我们可以告警或者重新建立连接。

关闭连接

  • WebSocket 是全双工通信,当客户端发送关闭请求时,服务端不一定立即响应,而是等服务端也同意关闭时再进行异步响应。
  • 下面是一个客户端关闭的例子:
Client: FIN=1, opcode=0x8, msg="1000"
Server: FIN=1, opcode=0x8, msg="1000"

使用 WebSocket 实现一个简易聊天室

  • 下面是一个简易聊天室小案例,任何人打开下面的网页都可以加入我们聊天室进行聊天,然后小红和小明加入了聊天:

简易聊天室

前端源码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>WebSocket Chat</title>
</head>
<body>
<div id="chat"></div>
<input type="text" id="messageInput" placeholder="Type your message">
<button onclick="sendMessage()">Send</button><script>const socket = new WebSocket('ws://localhost:8888');socket.onopen = (event) => {console.log('WebSocket connection opened:', event);};socket.onmessage = (event) => {const messageDiv = document.getElementById('chat');const messageParagraph = document.createElement('p');messageParagraph.textContent = event.data;messageDiv.appendChild(messageParagraph);};socket.onclose = (event) => {console.log('WebSocket connection closed:', event);};function sendMessage() {const messageInput = document.getElementById('messageInput');const message = messageInput.value;socket.send(message);messageInput.value = '';}
</script>
</body>
</html>

后端源码 Java

package chat;import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;import java.net.InetSocketAddress;public class ChatServer extends WebSocketServer {public ChatServer(int port) {super(new InetSocketAddress(port));}@Overridepublic void onOpen(WebSocket conn, ClientHandshake handshake) {System.out.println("New connection from: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());}@Overridepublic void onClose(WebSocket conn, int code, String reason, boolean remote) {System.out.println("Closed connection to: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());}@Overridepublic void onMessage(WebSocket conn, String message) {System.out.println("Received message: " + message);// Broadcast the message to all connected clientsbroadcast(message);}@Overridepublic void onError(WebSocket conn, Exception ex) {System.err.println("Error on connection: " + ex.getMessage());}@Overridepublic void onStart() {}public static void main(String[] args) {int port = 8888;ChatServer server = new ChatServer(port);server.start();System.out.println("WebSocket Server started on port: " + port);}
}

总结

  • WebSocket 是一种在客户端和服务器之间建立实时双向通信的协议。具备全双工、低延迟等优点,适用于实时聊天、多人协助、实时数据展示等场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/508544.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode题解】2809. 使数组和小于等于 x 的最少时间+2788. 按分隔符拆分字符串+410. 分割数组的最大值

文章目录 [2809. 使数组和小于等于 x 的最少时间](https://leetcode.cn/problems/minimum-time-to-make-array-sum-at-most-x/)思路&#xff1a; [2788. 按分隔符拆分字符串](https://leetcode.cn/problems/split-strings-by-separator/)思路&#xff1a; [410. 分割数组的最大…

设计模式(十三)抽象工厂模式

请直接看原文:设计模式&#xff08;十三&#xff09;抽象工厂模式_抽象工厂模式告诉我们,要针对接口而不是实现进行设计。( )-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- …

通信原理:通信的基本概念(第一节课)

1.通信的基本概念 1.1消息&#xff0c;信息与信号 我们先看一个调幅AM无线广播系统 我们信号举个例子&#xff1a; 可以看出&#xff0c;我们研究的参量不一样&#xff0c;对应的模拟和数字信号也会与我们看上去的不同。 信息&#xff1a; 生活中的例子来认识一下&#xff1…

Python——桌面摄像头软件(附源码+打包)

目录 一、前言 二、桌面摄像头软件 2.1、下载项目 2.2、功能介绍 三、打包工具&#xff08;nuitka&#xff09; 四、项目文件复制&#xff08;我全部合到一个文件里面了&#xff09; 五、结语 一、前言 看见b站的向军大叔用electron制作了一个桌面摄像头软件 但是&#x…

LabVIEW起重机工作参数远程监测系统

LabVIEW起重机工作参数远程监测系统 随着起重机技术的持续发展&#xff0c;对其工作参数的实时监控需求日益增加。设计了一个基于LabVIEW和TBox的起重机工作参数远程监测系统&#xff0c;能够实现起重机工作参数的实时采集、传输、解析和显示&#xff0c;有效提升起重机的性能…

自动化测试介绍、selenium用法(自动化测试框架+爬虫可用)

文章目录 一、自动化测试1、什么是自动化测试&#xff1f;2、手工测试 vs 自动化测试3、自动化测试常见误区4、自动化测试的优劣5、自动化测试分层6、什么项目适合自动化测试 二、Selenuim1、小例子2、用法3、页面操作获取输入内容模拟点击清空文本元素拖拽frame切换窗口切换/标…

【计算机网络】HTTPS 协议原理

https 一、HTTPS 是什么二、加密1. 加密概念2. 加密的原因3. 常见的加密方式&#xff08;1&#xff09;对称加密&#xff08;2&#xff09;非对称加密 三、数据摘要(数据指纹)四、HTTPS 的工作原理探究1. 只使用对称加密2. 只使用非对称加密3. 双方都使用非对称加密4. 非对称加…

信息系统项目管理师--项目立项管理

项⽬⽴项管理是对拟规划和实施的项⽬技术上的先进性、适⽤性&#xff0c;经济上的合理性、效益性&#xff0c;实施上的可能性、⻛险性以及社会价值的有效性、可持续性等进⾏全⾯科学的综合分析&#xff0c; 为项⽬决策提供客观依据的⼀种技术经济研究活动 项⽬建议与⽴项申请、…

代码随想录第46天|● 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II

文章目录 ● 121. 买卖股票的最佳时机思路一&#xff1a;贪心&#xff08;效率最快&#xff09;代码&#xff1a; 思路二&#xff1a;动态规划-dp数组代码&#xff1a; 思路三&#xff1a;动态规划 常数储存代码&#xff1a; ● 122.买卖股票的最佳时机II思路一&#xff1a;动态…

微信小程序(四十九)拦截器处理登入失败情况

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.拦截器判断处理失败与成功的情况 2.使用拦截器拒绝失败的情况&#xff0c;使网络请求后面的逻辑步骤不会执行 源码&#xff1a; index.wxml <button type"primary" bind:tap"onSubmit"…

Java面试题总结200道(二)

26、简述Spring中Bean的生命周期&#xff1f; 在原生的java环境中&#xff0c;一个新的对象的产生是我们用new()的方式产生出来的。在Spring的IOC容器中&#xff0c;将这一部分的工作帮我们完成了(Bean对象的管理)。既然是对象&#xff0c;就存在生命周期&#xff0c;也就是作用…

C#,无监督的K-Medoid聚类算法(K-Medoid Algorithm)与源代码

1 K-Medoid算法 K-Medoid&#xff08;也称为围绕Medoid的划分&#xff09;算法是由Kaufman和Rousseeuw于1987年提出的。中间点可以定义为簇中的点&#xff0c;其与簇中所有其他点的相似度最小。 K-medoids聚类是一种无监督的聚类算法&#xff0c;它对未标记数据中的对象进行聚…