Web端即时通讯必备技术:WebSocket快速入门

news2025/2/25 12:31:06

        随着Web应用程序的不断发展,越来越多的应用需要实现实时交互和通信。然而,传统的HTTP协议只支持单向通信,即客户端向服务器发送请求并接收响应。为了解决这一限制,WebSocket技术应运而生。本文将为大家介绍即时通讯技术 WebSocket的基本原理,并且讲解一个基于WebSocket + Node.js实现简易的一对一实时聊天的案例。

1、基本概念

WebSocket是一种HTML5提供的全双工通信协议(指可以在同一时间内允许两个设备之间进行双向发送和接收数据的通信协议),用于浏览器与服务器之间的实时通信。

WebSocket基于TCP传输协议,并且复用HTTP的握手通道(基于HTTP的 "keep-alive" 机制,允许在一次TCP连接中传送多个HTTP请求和响应)。建立WebSocket连接时,客户端会向服务器发送一个HTTP请求报文,其中包含升级协议的请求头,服务器在接收到该请求后会返回一个HTTP响应报文,其中包含升级协议的响应头。在收到服务器的响应后,客户端和服务器之间的连接就会升级为WebSocket连接,此时客户端和服务器之间的通信就不再需要使用HTTP协议的请求和响应报文,而是直接进行双向数据传输。因此,可以大大减少建立和断开连接的开销,并且实现更低的延迟和更高的吞吐量。

下面是它的优点:

1、实时性:与传统的HTTP请求/响应模式不同,WebSocket允许实时双向通信,使得服务器能够主动向客户端推送数据,而不需要客户端发起请求。

2、更少的网络流量:WebSockets使用更少的网络流量,因为在连接建立后,客户端和服务器之间的通信只需要很少的开销。

3、更少的延迟:由于WebSocket允许实时通信,因此它可以大大减少通信的延迟时间。

4、更少的服务器压力:WebSocket连接保持打开状态,因此服务器不需要为每个请求创建一个新的连接。这可以减轻服务器的负载并提高性能。

5、更好的跨域支持:WebSocket具有更好的跨域支持,因为它使用标准的HTTP握手来建立连接,可以使用与HTTP相同的跨域策略。

6、可扩展性:WebSocket可以轻松扩展以支持大量并发连接,因为它使用单个TCP连接来处理多个并发请求。

7、省电:WebSocket可以通过减少网络流量和延迟来减少移动设备的能耗,因此它在移动设备上的使用非常适合。

2、快速上手

2.1步骤说明**

WebSocket技术的运用主要分为3个步骤,以下分别说明:

  1. 建立握手连接客户端向服务器发送一个HTTP请求,其中包含Upgrade头部,表示要升级协议到WebSocket,然后服务器发送回一个带有Upgrade头部的HTTP响应,表示同意升级。接着,客户端和服务器就建立了WebSocket连接。

(1)客户端的请求头主要内容(采用HTTP请求报文格式,并且只支持GET方法)

GET ws://127.0.0.1:57924/2.html/ws HTTP/1.1

Host: 127.0.0.1:57924

Connection: Upgrade

Upgrade: websocket

Origin: http://127.0.0.1:57924

Sec-WebSocket-Key: 2DBoIM6oiUuKvzSmZnjdCA==

说明:

*Connection, Upgrade:Connection表示连接形式,Upgrade是升级的意思

*Upgrade: websocket:表示要升级为websocket协议

(2)服务端的响应头内容

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: 85fqPOwals3GjAFetTkCD04AfE4=

说明:返回状态代码101表示协议已切换,完成协议升级。

2、数据传输:建立WebSocket连接之后,客户端和服务器之间可以互相发送消息。WebSocket采用帧的形式进行数据传输,一个帧包含一个或多个数据片段。帧头部包含了帧的元信息,比如数据是否被分片、数据类型等信息。接收方会将关联的帧重新组装成完整的消息。

3、关闭连接:当不再需要连接时进行时,需要关闭的一方通过 ws.close() 方法进行关闭,该方法会发送一个包含关闭码的帧。接收到关闭码后,另一方也会发送一个带有关闭码的响应帧,表示同意关闭连接。

2.2 简单实现例子

1、使用Node.js建立WebSocket服务器代码( 这里使用了ws库来创建WebSocket服务器)

补充:Node.js是一个开源的跨平台JavaScript运行时环境node.js就是使用javascript编写,并且运行在服务器,也就是说node.js实现了使用js来开发后端

// 引入ws库

const WebSocket = require('ws')

// 建立websocket服务器

const server = new WebSocket.Server({ port: 8080 })

// 建立一个空的数据集合users

let users = new Set()

let count = 0

server.on('connection', function (ws) {

/* 每当有新用户连接了该WebSocket服务器,就会建立一个持久化的连接

并触发该函数,除非一方发送关闭帧或发生网络故障才会导致连接中断 */

// ws为当下连接的用户对象,这里把用户信息收集至users集合中

users.add(ws)

//统计进来的用户数

count++

console.log(count + '名用户连接了')

ws.on('message', function (message) {

/* 接收当下用户ws在客户端发送的消息之后,就会触发该函数,

形参message就是发来的信息,此时是二进制的数据 */

users.forEach(function (user) {

// 遍历所有用户,给非自己的其他用户发送消息

if (user !== ws) {

user.send(message.toString())

}

})

})

})

说明:

(1)当建立了一个WebSocket长连接后,会触发server.on('connection',连接函数)的连接函数,参数ws就表示当下的用户,并用users集合来收集用户;

(2)在连接函数里放入 ws.on('message', 消息函数),当该ws用户在客户端发送了消息,就会触发消息函数,形参message是二进制格式的消息;

(3)在消息函数里遍历users集合,给非自身的用户都发送当下ws用户发来的消息。

2、前端简易代码

const ws = new WebSocket('ws://localhost:8080')

ws.onopen = function () {

console.log('与服务器建立了websocket连接')

ws.send('hello') // 建立连接后,立马给服务器发送字符串信息

}

ws.onmessage = function (event) {

console.log('接收到服务端发送的其他用户的消息')

console.log('打印数据' + event.data)

}

说明:

(1)WebSocket是由HTML5提供的技术,所以此处可以直接new WebSocket创建一个连接,连接的协议要改为ws,端口号与服务器建立的要对应;

(2)当建立了连接就会触发ws.onopen事件函数,当接收消息就会触发ws.onmessage事件函数。

三、WebSocket + Node.js实现一对一聊天室

讲到这里大家应该已经了解了WebSocket快速实现的方式,下面我们就为大家讲解如何使用 WebSocket + Node.js 技术来实现简易版的一对一聊天室效果。

前端代码

1、HTML+CSS代码

<style>

#box {

width: 400px;

height: 200px;

overflow-y: scroll;

padding: 10px;

margin-bottom: 20px;

border: 1px solid rgb(156, 152, 152);

background-color: #f8f4f4;

}

/* 放置聊天信息的div,为了消息有左右展示的效率设置了display:flex */

#chat-window {

display: flex;

flex-direction: column;

}

#chat-window > div {

flex-grow: 1;

padding: 5px;

max-width: 70%;

}

#chat-window > div > div {

text-align: left;

word-wrap: break-word;

padding: 5px;

border-radius: 5px;

box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1);

}

#chat-window > div > span {

font-size: 12px;

color: #aaa6a6;

}

/* 收到对方发来的消息会动态生成类目为left-message的div标签,并设置左侧展示 */

.left-message {

align-self: flex-start;

}

/* 自己发送消息会动态生成类目为right-message的div标签,并设置右侧展示 */

.right-message {

text-align: right;

align-self: flex-end;

}

.left-message div {

background-color: #fff;

}

.right-message div {

background-color: #4dc86f;

}

</style>

<body>

一对一聊天室

​​

</div>

<input type="text" id="message" placeholder="输入消息" />

发送关闭聊天

</body>

说明:

(1)有新的聊天信息会创建新的dom,放入id为"chat-window"的div里,之所以外面还要包裹一个"box"是考虑消息条数过多时,要生成滚动条的效果,所以"box”div设置了固定高度和overflow-y: scroll样式;

(2)聊天效果区分了对方和自己发的消息,模仿一般聊天效果,自己信息会显示右侧,故类名为right-message,对方消息的div标签则类名是left-message,设置弹性盒子,并给自身设置align-self样式来实现左右效果。

页面效果:

2、JS代码

<script>

const ws = new WebSocket('ws://localhost:8080')

const sendBtn = document.getElementById('send')

const closeBtn = document.getElementById('close')

const messageInput = document.getElementById('message')

const chatWindow = document.getElementById('chat-window')

const box = document.getElementById('box')

ws.onopen = function (event) {

console.log('连接成功')

})

// 点击发送按钮时,在点击事件里使用ws.send()传我的消息给服务器

sendBtn.onclick = function (event) {

const message = messageInput.value

ws.send(message)

messageInput.value = ''

chatWindow.innerHTML += <div class="right-message"><span>我</span><div>${message}</div></div>

box.scrollTop = box.scrollHeight

}

// 给ws绑定message事件,当服务器接收对方发送的消息并传给我时会触发,event.data就是对方的消息内容

ws.onmessage = function (event) {

const message = event.data

chatWindow.innerHTML += <div class="left-message"><span>对方</span><div>${message}</div></div>

box.scrollTop = box.scrollHeight

}

// 点击关闭聊天,将中断连接,我再发送信息,对方将不能收到

closeBtn.onclick = function () {

ws.close()

}

</script>

说明:

(1)首先通过new WebSocket(服务器地址) 进行WebSocket连接,然后创建ws.onopen事件函数,在函数里验证是否连接成功;

(2)给发送按钮添加点击事件,事件函数里要获取发送的消息值,然后ws.send()方法把消息传递给服务器,同时创建dom插入页面,展示我发送的消息;

(3)给ws绑定message事件,这样我就能实时接收对方发送给服务器,服务器再传递给我的消息,获取消息信息,创建dom插入页面当中;

(4)给关闭聊天按钮添加了点击事件,点击关闭将中断该用户的WebSocket连接。

后端Node.js代码

const WebSocket = require('ws')

const server = new WebSocket.Server({ port: 8080 })

let users = new Set()

// 创建连接事件函数

server.on('connection', (ws) => {

users.add(ws)

// 创建接收客户端消息的事件函数

ws.on('message', (message) => {

// 此时消息message为二进制格式,需要转成字符串

message = message.toString()

users.forEach(function (user) {

if (user !== ws) {

user.send(message)

}

})

})

ws.on('close', () => {

users.delete(ws)

})

})

该后端代码和上面的建议案例基本一致,故不再说明

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 挂载云盘 NT只能挂载2T,使用parted挂载超过2T云盘

一、删除原来挂载好的云盘和分区 1、查看挂载号的云盘 fdisk -l 发现我们有5千多G但是只挂载了2T&#xff0c;心里非常的慌张&#xff01;十分的不爽&#xff01; 好&#xff0c;我们把它干掉&#xff0c;重新分区&#xff01; 2、解除挂载 umount /homeE 没保存跳转到&…

Elasticsearch:(一)ES简介

搜索引擎是什么&#xff1f;在不少开发者眼中&#xff0c;ES似乎就是搜索引擎的代名词&#xff0c;然而这实际上是一种误解。搜索引擎是一种专门用于从互联网中检索信息的技术工具&#xff0c;它主要可以划分为元搜索引擎、全文搜索引擎和垂直搜索引擎几大类。其中&#xff0c;…

【算法一则】矩阵置零 【矩阵】【空间复用】

题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2&#xff1a; …

设计模式代码实战-中间者模式

1、问题描述 小明正在设计一个简单的多人聊天室系统&#xff0c;有多个用户和一个聊天室中介者&#xff0c;用户通过中介者进行聊天&#xff0c;请你帮他完成这个系统的设计。 输入示例 3 User1 User2 User3 User1 Hello_All! User2 Hi_User1! User3 How_is_everyone? 输出…

写后端项目的分页查询时,解决分页不更新

写基于VueSpringBoot项目&#xff0c;实现分页查询功能时&#xff0c;改完代码后&#xff0c;发现页数不更新&#xff1a; 更改处如下&#xff1a; 显示如图&#xff1a; 发现页数没有变化&#xff0c;两条数据还是显示在同一页&#xff0c;而且每页都10条。且重启项目也没有更…

【408直通车】C+Python赋能数据结构:从底层原理到高级应用的蜕变之路——线性表

本专栏旨在通过使用C语言和Python分别实现各种考研常见数据结构&#xff0c;从底层原理和应用两个角度深入探索数据结构。通过深入理解数据结构的底层原理和掌握Python的高级特性&#xff0c;读者将能够全面掌握数据结构的知识&#xff0c;并且学会如何在实际应用中灵活运用。 …

查天气(Vue.js,Element UI)

演示图 几点注意 有亿点简陋&#xff0c;凑合能用&#xff0c;button一定要 !important 覆盖原本的 element ui &#xff0c;不然无效axios回调函数中 this 指向改变了&#xff0c;需要额外的保存一份服务器返回的数据比较复杂时&#xff0c;获取的时候需要注意层级结构method…

光伏电站智能勘探:无人机优势及流程详解

随着科技和互联网技术的不断发展&#xff0c;无人机在各个领域的应用越来越广泛&#xff0c;其中之一就是光伏电站智能勘探。利用无人机高清摄像头和传感器等设备&#xff0c;可以对光伏电站周边环境、日照情况、房屋状态进行全方面的勘探和记录&#xff0c;搭配卫星勘探、实地…

自动驾驶(八十四)---------中间件对比分析

很久没有写博客了&#xff0c;CSDN无故非法删了我第82篇&#xff0c;让我很恼火&#xff0c;一直提不起兴趣重新写一遍第82篇。但回初心&#xff0c;知识需要用自己的语言输出&#xff0c;所以今天对比分析自动驾驶中间件&#xff1a; 1. 中间件介绍 在自动驾驶架构中&#xf…

第14章 大数据与数据科学知识点梳理

第14章 大数据与数据科学知识点梳理&#xff08;附带页码&#xff09; ◼ 原则&#xff1a;组织应仔细管理与大数据源相关的元数据&#xff0c;以便对数据文件及其来源和价值进行准确的清单管理。P386 ◼ 大数据&#xff1a;数据量大&#xff08;Volume&#xff09;、数据更新…

嵌入式中C++指针使用方法总结

各位开发者大家好,在分享指针之前,先来看一下int *p[3]和int (*p)[3] 的区别。 int *p[3] p是一个数组,此数组有3个元素,每个元素都是int*类型,也就是指向整型数据的指针类型。 int a=10,b=20,c=30; int*p[3]={&a,&b,&c}; 而int(*p)[3]中的p是一个指向数组的…

浅谈Java的synchronized 锁以及synchronized 的锁升级

在Java中&#xff0c;synchronized关键字用于实现线程间的同步&#xff0c;确保同一时刻只有一个线程能够访问被同步的代码块或方法。当一个线程获得synchronized锁定后&#xff0c;其他试图访问同一锁的线程将被阻塞&#xff0c;直到锁被释放。 synchronized锁有两种基本形式…

计算机网络实验实验之VLAN的配置与分析

实验目的 了解什么是带内管理&#xff1b;熟练掌握如何使用telnet方式管理交换机&#xff1b;熟练掌握如何为交换机设置web方式管理&#xff1b;熟练掌握如何进入交换机web管理方式&#xff1b;了解交换机web配置界面&#xff0c;并能进行部分操作。 (6)了解VLAN原理&#xf…

python pygame事件与事件处理

本期是接上期python pygame库的略学内容最后一个步骤&#xff0c;游戏与玩家交互的内容。 一、什么是事件 游戏需要与玩家交互&#xff0c;因此它必须能够接收玩家的操作&#xff0c;并根据玩家的不同操作做出有针对性的响应。程序开发中将玩家会对游戏进行的操作称为事件&…

微服务架构与Dubbo

一、微服务架构 微服务架构是一种架构概念&#xff0c;旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。 分布式系统式若干独立系统的集合&#xff0c;但是用户使用起来好像是在使用一套系统。 和微服务对应的是单体式开发&#xff0c;即所有的功能打包在一个WAR…

关于CRMEB 商城系统商业授权的那些事儿

现在&#xff0c;很多时候我们都会听到“授权”这个词&#xff0c;在CRMEB的商城系统产品中&#xff0c;商业授权也是一个重要环节&#xff0c;今天&#xff0c;我们就来了解一下关于CRMEB商城系统授权的那些事儿。 一、为什么要进行商业授权&#xff1f; 正版商业授权是对用户…

【Linux】详解如何利用共享内存实现进程间通信

一、共享内存&#xff08;Shared Memory&#xff09;的认识 共享内存&#xff08;Shared Memory&#xff09;是多进程间共享的一部分物理内存。它允许多个进程访问同一块内存空间&#xff0c;从而在不同进程之间共享和传递数据。这种方式常常用于加速进程间的通信&#xff0c;因…

软考130-上午题-【软件工程】-系统维护

一、系统维护概述 软件维护是软件生命周期中的最后一个阶段&#xff0c;处于系统投入生产性运行以后的时期中&#xff0c;因此不属于系统开发过程。 软件维护是在软件已经交付使用之后为了改正错误或满足新的需求而修改软件的过程&#xff0c;即软件在交付使用后对软件所做的一…

李沐-19 卷积层【动手学深度学习v2】

记录下关于权重下标变换的理解&#xff1a; 从原来的Wi,j到Wi,j,k,l是从二维到四维的过程&#xff0c;如下图所示 对全连接层使用平移不变性和局部性得到卷积层&#xff0c;这是卷积层的引入&#xff0c;下方Vi,j,a,b--->Va,b表示了平移不变性&#xff0c;给a,b限制在||内保…

C语言 【函数】

1.函数概述 函数是一种可重用的代码块&#xff0c;用于执行特定任务或完成特定功能 函数作用&#xff1a;对具备相同逻辑的代码进行封装&#xff0c;提高代码的编写效率&#xff0c;实现对代码的重用 2. 函数的使用 2.1 无参无返回值 #include <stdio.h>// 函数名…