websocket详解

news2024/12/25 9:04:54

一、什么是Websocket

WebSocket 是一种在单个 TCP 连接上进行 全双工 通信的协议,它可以让客户端和服务器之间进行实时的双向通信。

WebSocket 使用一个长连接,在客户端和服务器之间保持持久的连接,从而可以实时地发送和接收数据。

在 WebSocket 中,客户端和服务器之间可以互相发送消息,客户端可以使用 JavaScript 中的 WebSocket API 发送消息到服务器,也可以接收服务器发送的消息。

二、Websocket特点

简单来说,websocket 具有 双向通信,实时性强,支持二进制,控制开销 的特点。

1、协议标识符是ws(如果加密,则为wss),服务器网址就是 URL

2、实时通信,服务器可以随时主动给客户端下发数据。

3、保持连接状态,Websocket需要先创建连接,所以是一种有状态的协议,之后通信时就可以省略部分状态信息。

4、控制开销,连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有2至10字节(和数据包长度有关);对于客户端到服务器的内容,头部还需要加上额外的4字节的掩码。

5、实现简单,建立在 TCP 协议之上,服务器端的实现比较容易,并且没有同源限制,客户端可以与任意服务器通信。

6、支持二进制传输,Websocket定义了二进制帧,可以发送文本,也可以发送二进制数据。

7、与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

8、支持扩展,用户可以扩展协议、实现部分自定义的子协议,如部分浏览器支持压缩等。

三、WebSocket与HTTP的区别

websocket和http都是基于TCP的应用层协议,使用的也是 80 端口(若运行在 TLS 之上时,默认使用 443 端口)。

区别主要就在于连接的性质和通信方式

WebSocket是一种双向通信的协议,通过一次握手即可建立持久性的连接,服务器和客户端可以随时发送和接收数据。

而HTTP协议是一种请求-响应模式的协议,每次通信都需要发送一条请求并等待服务器的响应。

WebSocket的实时性更好,延迟更低,并且在服务器和客户端之间提供双向的即时通信能力,适用于需要实时数据传输的场景。

四、常见应用场景

  1. 实时聊天:WebSocket能够提供双向、实时的通信机制,使得实时聊天应用能够快速、高效地发送和接收消息,实现即时通信。
  2. 实时协作:用于实时协作工具,如协同编辑文档、白板绘画、团队任务管理等,团队成员可以实时地在同一页面上进行互动和实时更新。
  3. 实时数据推送:用于实时数据推送场景,如股票行情、新闻快讯、实时天气信息等,服务器可以实时将数据推送给客户端,确保数据的及时性和准确性。
  4. 多人在线游戏:实时的双向通信机制,适用于多人在线游戏应用,使得游戏服务器能够实时地将游戏状态和玩家行为传输给客户端,实现游戏的实时互动。
  5. 在线客服:WebSocket可以用于在线客服和客户支持系统,实现实时的客户沟通和问题解决,提供更好的用户体验,减少等待时间。

五、websocket实例

在这里插入图片描述
为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

1)Websocket事件

  • onopen: 客户端和服务器建立连接后触发,被称为客户端和服务器之间的初始握手。如果接收到open, 说明已经连接成功,可以进行通信了。
  • onmessage: 接收到消息时触发。服务器发送给客户端的消息可包括纯文本消息,二进制数据(Blob消息或者ArrayBuffer消息)。
  • onerror: 响应意外故障时触发,在错误之后总是会终止连接。
  • onclose:连接关闭时触发。一旦连接关闭后,客户端和服务端将不会再进行消息的收发。也可主动调用close()方法关闭连接。

2)Websocket方法

  • send() : 在连接成功后关闭前,发送消息(onopen后和onclose前才可发送消息)
  • close() : 关闭连接
3)Websocket对象属性
  • readyState:只读属性,表示Websocket的连接状态。
    • CONNECTING — 正在连接中,对应的值为 0;
    • OPEN — 已经连接并且可以通讯,对应的值为 1;
    • CLOSING — 连接正在关闭,对应的值为 2;
    • CLOSED — 连接已关闭或者没有连接成功,对应的值为 3。
  • bufferedAmount:只读属性。已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
  • Protocol:打开握手期间使用的协议。

4)websocket请求报文

// websocket握手:客户端发送的请求头
GET wss://www.example.cn/webSocket HTTP/1.1  // 使用的https协议, 对应的wss请求
Host: www.example.cn
Connection: Upgrade  // 带upgrade头的http1.1消息必须含有connection头,表示任何接受此消息的人都在转发此消息之前处理掉connection中指定的域(即不转发upgrade域)
Upgrade: websocket  				// 定义转换协议的header域,如果服务器支持,客户端希望使用已经建立好的http(tcp)连接
Sec-WebSocket-Version: 13 	// 客户端支持的WebSocket协议的版本列表
Origin: http://example.cn 	// Origin为安全使用,防止跨站攻击,浏览器一般会使用这个来标识原始域,类似于Referer。但与Referer 不同的是,Origin 只包含了协议和主机名称
Sec-WebSocket-Key: afmbhhBRQuwCLmnWDRWHxw== // 客户端随机生成的字符串,服务器会使用此字段组装成另一个key值(构造出一个SHA-1 的信息摘要)放在握手返回信息里,用于客户端到服务器websocket的初始握手,避免夸协议攻击
Sec-WebSocket-Protocol: chat, superchat 		// 首标,告诉客户端应用程序可使用的协议
Sec-WebSocket-Extensions: permessage-deflate // 首标,permessage-deflate:协商使用传输数据压缩,client_max_window_bits:擦采用LZ77压缩算法时,滑动窗口相关SIZE大小

// websocket握手:服务器发出的响应头
HTTP/1.1 101 // 服务端响应101状态码、Upgrade和Sec-WebSocket-Accept首标才算连接成功,否则不能连接成功。
Server: nginx/1.12.2
Date: Sat, 11 Aug 2018 13:21:27 GMT
Connection: upgrade // 指定一项或多项协议名,按优先级排序,以逗号分隔,这里表示升级为 WebSocket 协议
Upgrade: websocket
Sec-WebSocket-Accept: sLMyWetYOwus23qJyUD/fa1hztc= // 根据Sec-WebSocket-Key加上特殊字符串,计算SHA-1摘要,再进行 Base64编码协议生成(可尽量避免普通HTTP请求被误认为WebSocket协议)
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15

在这里插入图片描述
在这里插入图片描述

5)简单应用示例

<template>
  <div>
    <input type="text" :value="inputVal" />
    <button @click="handleSend">send</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
  
const inputVal = ref("");

const handleSend = () => {
  socket.send(inputVal.value);
};

// 创建WebSocket对象,并指定服务器的地址
const socket = new WebSocket("ws://82.157.123.54:9010/ajaxchattest");

// 与服务器建立连接:发送消息到服务器
socket.onopen = () => {
  console.log("connect: ");
};
// 收到服务器发送的消息:event处理服务器返回的数据
socket.onmessage = (event) => {
  console.log("receive: ", event.data);
};
// 连接或通信过程中发生错误
socket.onerror = (event) => {
  console.log("errror: ", event.error);
};
// 与服务器断开连接
socket.onclose = (event) => {
  console.log("close: ", event.code);
};
</script>

六、websocket心跳机制

1、作用:使 WebSocket 连接保持长连接,避免断开连接的情况发生。同时,心跳机制也可以检查WebSocket连接的状态,及时处理异常情况。还可以减少WebSocket连接及服务器资源的消耗。

2、原理:是利用心跳包及时发送和接收数据,保证WebSocket长连接不被断开。

3、详细流程

  • 客户端建立WebSocket连接。

  • 客户端向服务器发送心跳数据包(心跳包是指在一定时间间隔内,WebSocket发送的空数据包),服务器接收并返回一个表示接收到心跳数据包的响应。

  • 当服务器没有及时接收到客户端发送的心跳数据包时,服务器会发送一个关闭连接的请求。

  • 服务器定时向客户端发送心跳数据包,客户端接收并返回一个表示接收到心跳数据包的响应。

  • 当客户端没有及时接收到服务器发送的心跳数据包时,客户端会重新连接WebSocket

4、实现方式

  1. 使用setInterval定时发送心跳包。对服务器造成很大的压力,因为即使WebSocket连接正常,也要定时发送心跳包,从而消耗服务器资源。

  2. 在前端监听到WebSocket的onclose()事件时,重新创建WebSocket连接。减轻了服务器的负担,但是在重连时可能会丢失一些数据。

5、WebSocket重连

重连意思就是在WebSocket断开之后重新建立连接,这里指由于异常断开需要重新连接。

常用实现方法有下:
1)前端监听WebSocket的onclose()事件,重新创建WebSocket连接。
2)使用WebSocket插件或库,例如Sockjs、Stompjs等。
3)使用心跳机制检测WebSocket连接状态,自动重连。
4)使用断线重连插件或库,例如ReconnectingWebSocket等。

6、通过WebSocket心跳机制,实现重连

思路: 在建立长连接的时候开启心跳 > 通过和服务端发送信息,得到服务端给返回的信息,然后重置心跳 > 清除时间,再重新开启心跳。(如果网络断开的话,会执行方法,重新连接)

<template>
	<div>
		<input type="text" :value="inputVal" />
  		<button @click="handleSend">send</button>
	</div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const inputVal = ref("");

let ws: any = null; // websocket实例
let isConnect: Boolean = false; // 连接标识 避免重复连接
let reciveCode: any = null; // 断线重连后,延迟5秒重新创建WebSocket连接,reciveCode用来存储延迟请求的代码
let timeoutObj: any = null; // 延时发送消息对象(启动心跳时新建这个对象,收到消息后重置这个对象)

// websocket重连
const reConnect = () => {
  // 如果已经连上就不在重连了
  if (isConnect) {
    return;
  }
  clearTimeout(reciveCode);
  // 延迟5秒重连 避免过多次过频繁请求重连
  reciveCode = setTimeout(() => {
    newWebSocket();
  }, 5000);
};

// 创建并初始化websocket实例
const newWebSocket = () => {
  // 判断当前环境是否支持Websocket
  if (window.WebSocket) {
    if (!ws) {
      // 创建WebSocket对象,并指定服务器的地址
      ws = new WebSocket("ws://82.157.123.54:9010/ajaxchattest");
    }
    // 与服务器建立连接
    ws.onopen = () => {
      console.log("connect: ");
      isConnect = true;
      // 5分钟发一次心跳,比server端设置的连接时间稍微小一点,在接近断开的情况下以通信的方式去重置连接时间。
      timeoutObj = setTimeout(() => {
        if (isConnect) ws.send(inputVal.value);
      }, 300000);
    };
    // 收到服务器发送的消息
    ws.onmessage = (event: any) => {
      console.log("receive: ", event, event.data);
      clearTimeout(timeoutObj);
    };
    // 连接或通信过程中发生错误
    ws.onerror = (event: any) => {
      console.log("errror: ", event.error);
      isConnect = false; //连接错误 需要重连
      reConnect();
    };
    // 与服务器断开连接
    ws.onclose = (event: any) => {
      console.log("close: ", event.code);
      isConnect = false;
      // 连接错误 需要重连
      reConnect();
    };
  } else {
    console.log("当前浏览器不支持websocket");
  }
};

const handleSend = () => {
  newWebSocket();
  if (ws.readyState === ws.OPEN) {
    // ws开启状态
    ws.send(inputVal.value);
  } else if (ws.readyState === ws.CONNECTING) {
    // 正在开启状态,则等待1s后重新调用
    setTimeout(function () {
      handleSend();
    }, 1000);
  } else {
    // 若未开启 ,则等待1s后重新调用
    setTimeout(function () {
      handleSend();
    }, 1000);
  }
};
</script>

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

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

相关文章

【Mysql学习笔记】1 - Mysql入门

一、Mysql5.7安装配置 下载后会得到zip 安装文件解压的路径最好不要有中文和空格这里我解压到 D:\hspmysql\mysql-5.7.19-winx64 目录下 【根据自己的情况来指定目录,尽量选择空间大的盘】 添加环境变量 : 电脑-属性-高级系统设置-环境变量&#xff0c;在Path 环境变量增加mysq…

js-webApi笔记1

目录 前言 Web API的概念 什么是DOM DOM树 1、查找元素 2、其他查找元素方法 3、操作元素 4、操作元素属性 5、 操作元素样式 style 6、操作自定义属性 7、 操作表单元素属性 8、事件 9、事件绑定 10、常用鼠标事件 11、定时器 12、定时器案例 前言 Web API的概念…

京东推出数据平台云海 API接口将达700个

1月16日消息&#xff0c;继上周面对企业用户发布京东电商云解决方案后&#xff0c;日前&#xff0c;京东云平台又发布了全新的数据开放平台——“云海”&#xff0c;以开放商家、商品、点击流等相关数据。 在京东主办&#xff0c;思路网协办的京东开放云服务合作伙伴2014峰会&…

leetcode刷题日志-151反转字符串中的单词

给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意&#xff1a;输入字符串 s中可能会存在前导空格、尾随…

加密数字货币:机遇与风险并存

随着区块链技术的发展和普及&#xff0c;加密数字货币逐渐走入人们的视线。作为一种以数字形式存在的资产&#xff0c;加密数字货币具有去中心化、匿名性和安全性高等特点&#xff0c;为人们提供了一种全新的支付方式和投资选择。然而&#xff0c;加密数字货币市场也存在着较高…

实在智能携手中国电信翼支付,全球首款Agent智能体亮相2023数字科技生态大会

11月10日-13日&#xff0c;中国电信与广东省人民政府联合主办的“2023数字科技生态大会”在广州隆重举行。本届大会以“数字科技焕新启航”为主题&#xff0c;邀请众多生态合作伙伴全方位展示数字科技新成果&#xff0c;包括数字新消费、产业数字化、智能电子、人工智能大模型等…

Vite Vue3+Element Plus框架布局

App根组件&#xff1a;框架布局 <template><el-container class"layout-container-demo" style"height: 98vh"><!-- 菜单栏 --><el-aside width"200px"><el-scrollbar><!-- router:是否启用 vue-router 模式。…

springcloud整合nacos实现服务注册

Nacos是一个开源的分布式系统服务和基础设施解决方案&#xff0c;用于实现动态服务发现、配置管理和服务治理。它可以帮助开发人员和运维团队更好地管理微服务架构中的服务实例、配置信息和服务调用。 Nacos提供了服务注册与发现、动态配置管理、服务路由和负载均衡等功能&…

02-3解析BeautifulSoup

一、基本简介 BeautifulSoup简称&#xff1a;bs4什么是BeatifulSoup&#xff1f;  BeautifulSoup&#xff0c;和lxml一样&#xff0c;是一个html的解析器&#xff0c;主要功能也是解析和提取数据优缺点&#xff1f;  缺点&#xff1a;效率没有lxml的效率高  优点&#xff1…

小游戏:贪吃蛇和俄罗斯方块(Java简单版)

贪吃蛇 package z; import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.util.ArrayList; import java.util.List; import java.util.Random;import javax.swin…

畅捷通+数环通iPaaS,实现无代码集成上千款应用

01 关于畅捷通 畅捷通信息化服务专家,为用户提供在线财务软件,云进销存管理软件,移动办公软件,帮助小微企业人、财、货、客的管理,全面服务小微企业并提供社交化、个性化、服务化、小量化的生意管理支持。 企业除了畅捷通&#xff0c;还有大大小小其他的系统&#xff0c;面临着…

听GPT 讲Rust源代码--library/core/src(6)

题目来自 A Gentle Introduction To Rust[1] File: rust/library/core/src/num/dec2flt/common.rs 在Rust源代码中&#xff0c;rust/library/core/src/num/dec2flt/common.rs的作用是定义了一些用于十进制到浮点数转化的共享逻辑。以下是对该文件内容的详细介绍&#xff1a; Bi…

Linux磁盘分区快速上手(讲解详细)

一、磁盘分区 在Linux中&#xff0c;磁盘是通过分区来使用的。分区是将一个硬盘划分成几个逻辑部分来使用&#xff0c;在每个分区中可以存储不同的文件系统。因此&#xff0c;在挂载磁盘之前&#xff0c;我们需要先对磁盘进行分区。磁盘分区的过程可以通过命令行工具或图形界面…

国家药品价格查询官网-在线网站查询方法

查询药品上市价格对于个人和机构来说都是非常有必要的&#xff0c;对个人可以很好的验证该药品是否存在虚高的情况&#xff0c;对药企来说可以根据同类药品市场价格指导自产药品的定价&#xff0c;对其它机构来说了解药品价格可以帮助选择价格合理的药品供应商&#xff0c;降低…

自费出国|药学研究人员赴澳大利亚墨尔本大学访学

澳大利亚的创新药物研发在世界上一直处于领先地位&#xff0c;考虑到签证因素&#xff0c;专职药学研究的H老师将访学目标国家定位在澳大利亚。我们为其落实了墨尔本大学的职位&#xff0c;导师的研究课题与H老师的兴趣高度契合&#xff0c;最终顺利签证并如期出国。 H老师背景…

测试人员如何提交一条高质量的bug

测试人员在测试软件过程中&#xff0c;发现bug是必然的&#xff0c;那么发现bug后就要提交bug到缺陷管理系统中&#xff0c;如何提交一条高质量的bug&#xff0c;是每一个测试人员值得深思的问题&#xff0c;如果bug提交的不规范&#xff0c;不准确会导致开发人员理解错误&…

7条软件测试的基本原则

软件测试的原则是指帮助测试团队有效地利用他们的时间和精力来发现测试项目的隐藏bug的指导方针。从实践和研究中总结得出以下 7 条软件测试的基本原则&#xff0c;以便测试人员在软件测试领域广泛应用。 一、测试证明软件存在缺陷-Testing shows presence of defects 测试只能…

在已安装Anaconda环境下配置沐神(李沐老师)动手学深度学习环境

沐神配置环境视频 B站李沐老师动手学深度学习环境配置视频 在windows中配置沐神深度学习环境 前提&#xff1a;安装了Anaconda基本环境&#xff0c;了解Jupyter NoteBook 1.打开 Anaconda Prompt 2.创建虚拟环境 create conda -n d2l-zh python3.8 pip3.激活虚拟环境 con…

菲律宾shopee怎么推广?shopee菲律宾站点什么好卖?——站斧浏览器

菲律宾shopee怎么推广 首先&#xff0c;要想在Shopee上成功推广自己的店铺&#xff0c;关键是提升店铺的曝光率。有多种方式可以增加店铺的曝光率&#xff0c;其中之一是使用Shopee提供的广告服务。 Shopee广告分为首页广告和搜索广告两种形式。商家可以根据自己的需求选择适…

vue项目中设置background: url() 是行内样式不生效,样式表是可以的

[TOC](vue项目中设置background: url() 是行内样式不生效&#xff0c;样式表是可以的) 首先&#xff1a;如果不是项目中普通的一个index.html中是可以的 一、原因 在Vue项目中&#xff0c;行内样式和样式表的编译规则是有所不同的。当你在Vue组件的行内样式中使用相对路径引用图…