Web实时通信的学习之旅:WebSocket入门指南及示例演示

简介: Web实时通信的学习之旅:WebSocket入门指南及示例演示

WebSocket的出现,使得浏览器具备了实时双向通信的能力。且它不在需要进行3次握手与4次挥手,只需要在客户端创建一个socket实例并且提供它所要连接服务端的IP地址和端口,而服务端创建另一个socket并绑定本地端口进行监听,然后客户端进行连接服务端,服务端接受连接之后双方建立了一个端对端的TCP连接,在该连接上就实现双向通讯了。本文由浅入深,介绍了WebSocket如何建立连接、交换数据的细节,以及数据帧的格式。此外,还简要介绍了针对WebSocket的安全攻击,以及协议是如何抵御类似攻击的。

WebSocket的特点

1、工作原理

浏览器发出webSocket的连线请求,服务器发出响应,这个过程称为握手,握手的过程只需要一次,就可以实现持久连接。

WebSocket 的工作原理如下:

  • 客户端向服务器发送一个 HTTP 请求,请求建立 WebSocket 连接。
  • 服务器收到请求后,会返回一个 HTTP 响应,响应中包含一个 101 Switching Protocols 状态码,表示同意建立 WebSocket 连接。
  • 服务器和客户端通过 TCP 连接进行通信,数据格式为 JSON、二进制或文本。

2、特点

WebSocket是真正的全双工通信机制,建立连接后客户端与服务器端是完全平等的,可以互相主动请求。而HTTP长连接基于HTTP,是传统的客户端对服务器发起请求的模式。 HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,消息交换效率低。Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据,这显然和原有的HTTP协议有区别所以它需要对服务器和客户端都进行升级才能实现,当然在现在这个时代,我们的主流浏览器都是支持HTML5的,使用时我们直接使用即可。

  • 实时性:服务器可以主动向客户端发送消息,实现实时通信。
  • 双向通信:客户端和服务器之间可以同时发送和接收数据。
  • 性能:WebSocket 连接建立后,数据传输效率更高,减少了 HTTP 请求的次数。
  • 兼容性:WebSocket 协议在大多数浏览器中得到了支持,无需额外插件。

3、WebSocket 协议介绍

  • WebSocket 协议的底层协议也是TCP协议
  • WebSocket 协议的标识符为ws,加密后为wss
  • WebSocket 协议没有同源限制,即WebSocket 协议可以跨域通信
  • WebSocket 协议是有状态的,是前后端交互的长连接,即建立连接后可以保持连接状态,通信时可以省略部分状态信息
  • WebSocket 协议可以发送文本,同时也可以发送二进制数据
4、安全性

WebSocket 协议本身是安全的,但你需要确保 WebSocket 连接是通过 HTTPS 协议建立的,以防止中间人攻击。在 Node.js 中,你可以使用 wss 模块来创建一个安全的 WebSocket 服务器。

WebSocket的使用

一、服务端

1、创建实例:创建一个webScoket实例对象
 //创建一个WebSocket服务器,在3000端口启动
 const WebSocket = require('ws')
 const server = new WebSocket.Server({port:3000})

1.1、WebSocket.Server(options[,callback])方法中options对象所支持的参数

(1)host:绑定服务器的主机名

(2)port:绑定服务器的端口号

(3)backlog:挂起连接队列的最大长度

(4)server:预先创建的node.js http/s服务器

(5)verifyClient:可用于验证传入连接的函数

(6)handleProtocols:可用于处理WebSocket子协议的函数

(7)path:仅接受与此路径匹配的连接

(8)noServer:不启用服务器模式

(9)clientTracking:指定是否跟踪客户端

(10)perMessageDeflate:启用/禁用消息压缩

(11)maxPayload:允许的最大消息大小(以字节为单位)

1.2、同样也有一个加密的 wss:// 协议。类似于 WebSocket 中的 HTTPS。

  • wss:// 协议不仅是被加密的,而且更可靠。
  • 因为 ws:// 数据不是加密的,对于任何中间人来说其数据都是可见的。并且,旧的代理服务器不了解 WebSocket,它们可能会因为看到“奇怪的” header 而中止连接。
  • 另一方面,wss:// 是基于 TLS 的 WebSocket,类似于 HTTPS 是基于 TLS 的 HTTP),传输安全层在发送方对数据进行了加密,在接收方进行解密。因此,数据包是通过代理加密传输的。它们看不到传输的里面的内容,且会让这些数据通过。
2、监听连接:ws通过connection事件来监听连接

只要有WebSocket连接到该服务器,就会触发’connection’事件;req对象可以用来获取客户端的信息,如ip、端口号

// 监听连接事件
server.on('connection',function connection(ws,req){
     const ip = req.socket.remoteAddress
     const port = req.socket.remotePort
     const clientName = ip + port
     console.log('%s is connected ',clientName)
 })

3、发送数据:ws通过send()方法来发送数据
 server.on('connection',function connection(ws,req){
     const ip = req.socket.remoteAddress
     const port = req.socket.remotePort
     const clientName = ip + port
     
     // 发送消息到客户端
     ws.send('Welcome ' + clientName)
 })

send(data [,options][,callback])

data:发送的数据

options对象:

  • (1)compress:指定数据是否需要压缩。默认为true
  • (2)binary:指定数据是否通过二进制传送。默认是自动检测
  • (3)mask:指定是否应遮罩数据。
  • (4)fin:指定数据是否为消息的最后一个片段。默认为true
4、接收数据:ws通过message事件来接收数据

当客户端有消息发送给服务器时,服务器就能够触发该消息

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

    // 监听接收消息事件
     ws.on('message',function incoming(message){
         console.log('received: %s from %s',message,clientName)
         server.clients.forEach(function each(client){
             if(client.readyState === WebSocket.OPEN){
                 client.send(clientName +" -> " + message)
             }
         })
     })
 })

5、关闭WebSocket服务器:通过监听close事件关闭服务器
server.on('close',function close(){
 console.log('disconnected')
})


二、客户端

创建了一个webScoket实例对象常用属性和方法的介绍

属性 说明
url 当前连接的webScoket接口地址
readyState 当前连接的状态: 0:正在链接中 1:已经链接并且可以通讯 2:连接正在关闭 3;连接已关闭或者没有链接成功
onopen 连接成功的回调函数
onerror 连接失败的回调函数
onmessage 从服务端接受到信息的回调函数
onclose 连接关闭的回调函数
binaryType 使用二进制的数据类型连接
protocol 服务器选择的下属协议
bufferedAmount 未发送至服务器的二进制字节数
close() 关闭当前连接
send(data) 发送消息到服务器
1、客户端实现WebScoket连接
// 创建 WebSocket 连接
const ws = new WebSocket('ws://localhost:3000')

// 连接打开时触发
ws.onopen = function () {
  console.log('我们连接成功啦...')
  
  // 发送消息到服务器
  webSocket.send('Hello!')
}

// 连接出错时触发
ws.onerror = function () {
  console.log('连接失败了...')
}

// 接收到服务器消息时触发
ws.onmessage = function (e) {
  console.log('服务端传来数据啦...' + e.data)
}

// 连接关闭时触发
ws.onclose = function () {
  console.log('连接关闭了...')
}
2、WebScoket的重连机制

当我们正在使用WebScoket的时候,难免会出现WebScoket的断联,这个时候,我们只需要在onclose的回调函数中,重新链接即可

ws.onclose = function (e) {
   // 1每10秒重连一次,直到连接成功
    setTimeout(function () {
   // 重新调用连接webSocket事件
     ws = new WebSocket('ws://192.168.31.19:8081/')
   ws.onopen = function () {
     console.log('连接成功...')
        } 
         }, 10000);
        };
3、WebScoket的心跳保活

websocket长连接有默认的超时时间(1分钟),也就是说,超过一定的时间客户端和服务器之间没有发生任何消息传输,连接会自动断开;除此之外,服务器或防火墙一般也会在一段时间不活动并超时之后终止外部的长连接。因此,若需要使客户端一直保持连接,就需要设置心跳保活机制了。

实现原理:我们可以每次在 每次保持心跳保活的时候,向WebScoket发送一条消息,证明我们还"活着"

var timeout = 1000 * 30 //心跳间隔  
var timeoutTimer=null //保持心跳的定时器
  timeoutTimer = setTimeout(function () {
    ws.send('HeartBeat')
  }, timeout)
4、客户端主动断开连接
// 客户端主动断开连接
ws = new WebSocket('ws://192.168.31.19:8081/')
ws.close();
5、WebScoket添加token的几种方法
5.1、使用send发送参数
var  ws = new WebSocket("ws://" + url );
ws.onopen=function(){
    ws.send(token)
}
5.2、请求地址中携带参数
var  ws = new WebSocket("wss://" + url?token );
5.3、基于协议头

websocket请求头中可以包含Sec-WebSocket-Protocol这个属性,该属性是一个自定义的子协议。它从客户端发送到服务器并返回从服务器到客户端确认子协议。我们可以利用这个属性添加token。

var  ws = new WebSocket("ws://" + url,[token]);

三、入门例子

例子包括了WebSocket服务端、WebSocket客户端。

1、服务端

Node使用ws创建WebSocket服务器

1.1、ws模块:

是一个用于支持WebSocket客户端和服务器的框架。它易于使用,功能强大,且不依赖于其他环境

1.2、安装ws:
npm install ws
1.3、创建WebSocket服务器:

启动3000端口。当有新的连接请求到达时,打印日志,然后延迟两次向客户端发送消息。当收到到来自客户端的消息时,同样打印日志。

server.js

var WebSocket = require('ws');

var wss = new WebSocket.Server({
    port: 3000
});

// 创建一个TextDecoder实例来处理字符串
const decoder = new TextDecoder('utf-8');

wss.on('connection', function connection(ws) {
    console.log('server: receive connection.');

    ws.on('message', function incoming(message) {
        console.log('server: received', decoder.decode(message));
    });
    let data1 = {
        name: 'zhangsan',
        age: 18
    }
    let data2 = {
        name: 'lisi',
        age: 19
    }
    let data3 = 'wangwu'
    sendData(ws, data1, 1000 * 60 * 1)
    sendData(ws, data2, 1000 * 60 * 2)
    sendData(ws, data3, 1000 * 60 * 3)
});

const sendData = (ws, data = '', delay = 1000) => {
    if (!data) return
    if (typeof data === 'object') data = JSON.stringify(data)
    setTimeout(() => {
        ws.send(data);
    }, delay)
}

2、客户端

向3000端口发起WebSocket连接。连接建立后,打印日志,同时向服务端发送消息。接收到来自服务端的消息后,同样打印日志。

app.vue

const ws = new WebSocket('ws://localhost:3000');
ws.onopen = function () {
    console.log('我们连接成功了');
    ws.send('hello');
};
ws.onmessage = function (e) {
    console.log('服务端传来数据了:',e.data);
};
ws.onclose = function () {
    console.log('连接关闭了');
};
ws.onerror = function (err) {
    console.log('连接失败了', err);
};
3、运行结果

可分别查看服务端、客户端的日志,这里不展开。

3.1、服务端输出:
server: receive connection.
server: received hello
3.2、客户端输出:
我们连接成功了
服务端传来数据了:{"name":"zhangsan","age":18}
服务端传来数据了:{"name":"lisi","age":19}

总结

WebSocket 是一种强大的网络通信协议,它允许服务器和客户端之间进行实时、双向通信。在 WebSocket 连接中,服务器可以主动向客户端发送消息,这对于实时应用来说非常重要。通过使用 JavaScript 和后端语言,你可以轻松实现 WebSocket 通信。在实际应用中,WebSocket 已被广泛应用于在线聊天、股票交易、游戏等领域。

WebSocket 是一种在浏览器和服务器之间建立持久连接的现代方式。

  • WebSocket 没有跨源限制
  • 浏览器对 WebSocket 支持很好
  • 可以发送/接收字符串和二进制数据

WebSocket 方法:

  • socket.send(data)
  • socket.close([code], [reason])

WebSocket 事件:

  • open
  • message
  • error
  • close

WebSocket 自身并不包含重新连接(reconnection),身份验证(authentication)和很多其他高级机制。因此,有针对于此的客户端/服务端的库,并且也可以手动实现这些功能。


有时为了将 WebSocket 集成到现有项目中,人们将主 HTTP 服务器与 WebSocket 服务器并行运行,并且它们之间共享同一个数据库。对于 WebSocket 请求使用一个通向 WebSocket 服务器的子域 wss://ws.site.com,而 https://site.com 则通向主 HTTP 服务器。


目录
相关文章
|
安全 关系型数据库 测试技术
学习Python Web开发的安全测试需要具备哪些知识?
学习Python Web开发的安全测试需要具备哪些知识?
365 61
|
10月前
|
缓存 前端开发 应用服务中间件
Web端实时通信技术SSE在携程机票业务中的实践应用
本文介绍了携程机票前端基于Server-Sent Events(SSE)实现服务端推送的企业级全链路通用技术解决方案。文章深入探讨了 SSE 技术在应用过程中包括方案对比、技术选型、链路层优化以及实际效果等多维度的技术细节,为类似使用场景提供普适性参考和借鉴。
395 7
|
安全 Java 数据安全/隐私保护
springSecurity学习之springSecurity过滤web请求
通过配置 Spring Security 的过滤器链,开发者可以灵活地管理 Web 请求的安全性。理解核心过滤器的作用以及如何配置和组合这些过滤器,可以帮助开发者实现复杂的安全需求。通过具体的示例代码,可以清晰地了解 Spring Security 的配置方法和实践。
645 23
|
SQL 安全 前端开发
Web学习_SQL注入_联合查询注入
联合查询注入是一种强大的SQL注入攻击方式,攻击者可以通过 `UNION`语句合并多个查询的结果,从而获取敏感信息。防御SQL注入需要多层次的措施,包括使用预处理语句和参数化查询、输入验证和过滤、最小权限原则、隐藏错误信息以及使用Web应用防火墙。通过这些措施,可以有效地提高Web应用程序的安全性,防止SQL注入攻击。
661 2
|
网络协议 API 网络安全
Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
2855 0
|
5月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
513 4
|
9月前
|
缓存 JavaScript 前端开发
鸿蒙5开发宝藏案例分享---Web开发优化案例分享
本文深入解读鸿蒙官方文档中的 `ArkWeb` 性能优化技巧,从预启动进程到预渲染,涵盖预下载、预连接、预取POST等八大优化策略。通过代码示例详解如何提升Web页面加载速度,助你打造流畅的HarmonyOS应用体验。内容实用,按需选用,让H5页面快到飞起!
|
9月前
|
JavaScript 前端开发 API
鸿蒙5开发宝藏案例分享---Web加载时延优化解析
本文深入解析了鸿蒙开发中Web加载完成时延的优化技巧,结合官方案例与实际代码,助你提升性能。核心内容包括:使用DevEco Profiler和DevTools定位瓶颈、四大优化方向(资源合并、接口预取、图片懒加载、任务拆解)及高频手段总结。同时提供性能优化黄金准则,如首屏资源控制在300KB内、关键接口响应≤200ms等,帮助开发者实现丝般流畅体验。
|
前端开发 JavaScript Shell
鸿蒙5开发宝藏案例分享---Web页面内点击响应时延分析
本文为鸿蒙开发者整理了Web性能优化的实战案例解析,结合官方文档深度扩展。内容涵盖点击响应时延核心指标(≤100ms)、性能分析工具链(如DevTools时间线、ArkUI Trace抓取)以及高频优化场景,包括递归函数优化、网络请求阻塞解决方案和setTimeout滥用问题等。同时提供进阶技巧,如首帧加速、透明动画陷阱规避及Web组件初始化加速,并通过优化前后Trace对比展示成果。最后总结了快速定位问题的方法与开发建议,助力开发者提升Web应用性能。
|
9月前
|
JSON 开发框架 自然语言处理
【HarmonyOS Next之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(三)
本文主要介绍了应用开发中的三大核心内容:生命周期管理、资源限定与访问以及多语言支持。在生命周期部分,详细说明了应用和页面的生命周期函数及其触发时机,帮助开发者更好地掌控应用状态变化。资源限定与访问章节,则聚焦于资源限定词的定义、命名规则及匹配逻辑,并阐述了如何通过 `$r` 引用 JS 模块内的资源。最后,多语言支持部分讲解了如何通过 JSON 文件定义多语言资源,使用 `$t` 和 `$tc` 方法实现简单格式化与单复数格式化,为全球化应用提供便利。
331 104