服务器 > 网络 > websocket

Websocket的用法及常见应用场景

34人参与 2025-12-16 websocket

一、什么是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事件

2)websocket方法

参数:

参数:

3)websocket对象属性

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)websocket连接生命周期

6)简单应用示例

<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、详细流程

4、实现方式

5、websocket重连

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

常用实现方法有下:

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>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

您想发表意见!!点此发布评论

推荐阅读

检查 Nginx 是否启动的几种方法

12-05

Nginx配置WSS安全WebSocket代理的实现

12-05

Nginx WebSocket长连接及数据容量配置实践

12-27

Nginx使用Prometheus+Grafana实现日志分析与监控

12-27

深入理解NumPy 的 np.column_stack的实现

01-07

Nginx代理WebSocket失败的完整排查过程

11-14

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论