Websocket的基本认识、使用与封装

news2024/11/18 23:40:47

目录

一、Websocket是什么

二、Websocket的基本使用

使用介绍

第一步

第二步

第三步

第四步

常用API介绍 

WebSocket(url[, protocols])

WebSocket.readyState

 WebSocket.send(data)

WebSocket.close([code[, reason]])

WebSocket.bufferedAmount

WebSocket.extensions

WebSocket.binaryType

三、Websocket的封装

vue代码

react代码


一、Websocket是什么

        当一个Web应用程序需要实现实时双向通信时,传统的 HTTP 协议并不是最佳选择,因为HTTP是一个请求/响应协议,它的工作方式是客户端发送一个请求给服务器,服务器然后响应该请求,并发送一个响应给客户端。这种模式通常是单向的,客户端只能发起请求,而服务器只能响应请求。这意味着,客户端无法在不发出新请求的情况下接收来自服务器的新数据。

        WebSocket 协议就是为了解决这个问题而产生的,它可以在客户端和服务器之间建立持久的连接,以便实现双向通信。在建立连接之后,客户端和服务器可以随时发送消息,而不需要通过HTTP请求/响应的方式进行通信。此外,WebSocket还支持二进制数据的传输,这使得它更加灵活,可以用于许多不同的应用程序场景。

WebSocket协议的工作方式如下:

  1. 客户端向服务器发起一个WebSocket握手请求。这个请求与HTTP请求非常相似,但包含了一些附加的头部信息,以表示这是一个WebSocket请求。
  2. 服务器对该请求进行响应,包含一个状态码和一些头部信息。这个响应是HTTP响应,但同样包含了一些附加的头部信息,以表示这是一个WebSocket响应。
  3. 客户端和服务器之间的连接现在已经建立,并且可以进行双向通信了。客户端和服务器都可以随时发送消息,这些消息会被封装为WebSocket帧并通过WebSocket连接进行传输。

        需要注意的是,WebSocket协议与传统的HTTP协议不同,因为它不是基于请求/响应模式的。这意味着,一旦连接建立,客户端和服务器就可以随时发送消息,而不需要等待对方先发出请求。此外,WebSocket协议还支持心跳包机制,可以检测连接是否还处于活动状态。

        总之,WebSocket协议提供了一种高效、可靠、灵活的方式来实现Web应用程序之间的实时双向通信。它是一个强大的工具,可以用于许多不同的应用程序场景,包括在线游戏、实时聊天、数据传输和多人协作等等。

二、Websocket的基本使用

使用介绍

        前端使用WebSocket通常需要使用浏览器提供的WebSocket API,该API可以通过JavaScript代码与WebSocket服务器建立连接,并在连接建立后进行数据传输。

第一步

        创建一个WebSocket对象。可以使用以下代码创建一个WebSocket对象:

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

        在创建WebSocket对象时,需要传递WebSocket服务器的地址和端口号作为参数。WebSocket服务器地址可以使用ws://wss://前缀表示,ws://表示使用普通的HTTP协议进行通信,wss://表示使用加密的HTTP协议进行通信。

第二步

        监听WebSocket事件。WebSocket API提供了几种事件类型,可以通过这些事件来处理WebSocket的连接状态和数据传输。下面是常用的事件类型:

  • open:WebSocket连接成功时触发。
  • message:接收到WebSocket服务器发送的消息时触发。
  • error:WebSocket连接出错时触发。
  • close:WebSocket连接关闭时触发。

可以使用下面的代码监听WebSocket事件:

socket.addEventListener('open', (event) => {
  console.log('WebSocket连接已打开');
});

socket.addEventListener('message', (event) => {
  console.log('接收到消息:', event.data);
});

socket.addEventListener('error', (event) => {
  console.log('WebSocket连接出错:', event);
});

socket.addEventListener('close', (event) => {
  console.log('WebSocket连接已关闭');
});

第三步

        发送数据。可以使用WebSocket.send()方法向WebSocket服务器发送数据。该方法接受一个字符串或一个二进制数据对象作为参数。下面是一个例子: 

        这里需要注意的是如果传输的数据为对象格式,应转换为JOSN格式进行传输。  

socket.send('Hello, WebSocket!');

第四步

        关闭连接。可以使用WebSocket.close()方法关闭WebSocket连接。

socket.close();

常用API介绍 

WebSocket(url[, protocols])

        创建WebSocket对象。其中,url参数是WebSocket服务器的地址,protocols参数是一个可选的字符串或字符串数组,表示WebSocket协议的子协议列表。(见使用介绍第一步)

WebSocket.readyState

        WebSocket对象的只读属性,表示当前WebSocket的连接状态,它的值为下面四个之一:

  • 0 - 表示WebSocket连接尚未建立。
  • 1 - 表示WebSocket连接已建立,可以进行通信。
  • 2 - 表示WebSocket连接正在关闭。
  • 3 - 表示WebSocket连接已经关闭或者连接不能打开。
console.log(this.webSocket.readyState)

 WebSocket.send(data)

        向WebSocket服务器发送数据。其中,data参数可以是一个字符串、一个二进制数据对象或者一个Blob对象。(见使用介绍第三步)

WebSocket.close([code[, reason]])

关闭WebSocket连接。其中,code参数表示关闭代码,reason参数表示关闭原因。(见使用介绍第四步)

WebSocket.bufferedAmount

        WebSocket的bufferedAmount属性表示已经被send()方法发送但还没有被发送到网络层的数据量。在发送数据的过程中,如果发送的数据量大于WebSocket的缓冲区大小,那么这些数据就会被暂时保存在WebSocket的缓冲区中,直到网络层可以接受这些数据时再发送出去。

const socket = new WebSocket('ws://localhost:8080');
console.log('初始bufferedAmount:', socket.bufferedAmount);
socket.send('Hello, WebSocket!');
console.log('发送后bufferedAmount:', socket.bufferedAmount);

WebSocket.extensions

        WebSocket的extensions属性是一个只读属性,它表示WebSocket服务器支持的扩展列表。

const socket = new WebSocket('ws://localhost:8080');
console.log('WebSocket服务器支持的扩展:', socket.extensions);

WebSocket.binaryType

        WebSocket的binaryType属性表示在收到二进制数据时使用的编码方式,默认值是"blob"。可以将其设置为"arraybuffer"来使用ArrayBuffer对象来处理二进制数据。

const socket = new WebSocket('ws://localhost:8080');
socket.binaryType = 'arraybuffer';
socket.addEventListener('message', (event) => {
  const arrayBuffer = event.data;
  // 处理二进制数据
});

三、Websocket的封装

vue代码

import Vue from 'vue'
import { Message } from 'element-ui'
let v = new Vue()
v.$message = Message;
var webSocket = null;
var isConnect = false; //连接状态
var globalCallback = function(e){ console.log(e) };//定义外部接收数据的回调函数
var reConnectNum = 0;//重连次数

var websocketUrl =  process.env.VUE_APP_API_WEBSOCKET_URL;

//心跳设置
var heartCheck = {
    heartbeatData:{
        DevID:{
            value:Vue.ls.get('devid')
        },
        DevHeart:{
            value:"1"
        }   
    },//心跳包
    timeout: 60 * 1000, //每段时间发送一次心跳包 这里设置为60s
    heartbeat: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)
    start: function () {
        this.heartbeat = setInterval(()=>{
            if (isConnect){
                webSocketSend(this.heartbeatData);
            }else{
                this.clear();
            }
        }, this.timeout);
    },
    reset: function () {
        clearInterval(this.heartbeat);
        this.start();
    },
    clear:function(){
        clearInterval(this.heartbeat);
    }
}

//初始化websocket
function initWebSocket(callback) {
    //此callback为在其他地方调用时定义的接收socket数据的函数
    if(callback){
        if(typeof callback == 'function'){
            globalCallback = callback     
        }else{
            throw new Error("callback is not a function")
        }
    }
    if ("WebSocket" in window) {
        webSocket = new WebSocket(websocketUrl);//创建socket对象
    } else {
        Message({
            message: '该浏览器不支持websocket!',
            type: 'warning'
        });
        return
    }
    //打开
    webSocket.onopen = function() {
        webSocketOpen();
    };
    //收信
    webSocket.onmessage = function(e) {
        webSocketOnMessage(e);
    };
    //关闭
    webSocket.onclose = function(e) {
        webSocketOnClose(e);
    };
    //连接发生错误的回调方法
    webSocket.onerror = function(e) {
        webSocketonError(e);
    };
}

//连接socket建立时触发
function webSocketOpen() {
    console.log("WebSocket连接成功");
    //首次握手
    webSocketSend(heartCheck.heartbeatData);
    isConnect = true;
    heartCheck.start();
    reConnectNum = 0;
}

//客户端接收服务端数据时触发,e为接受的数据对象
function webSocketOnMessage(e) {
    console.log("websocket信息:");
    console.log(e.data)
    const data = JSON.parse(e.data);//根据自己的需要对接收到的数据进行格式化
    globalCallback(data);//将data传给在外定义的接收数据的函数,至关重要。
}

//socket关闭时触发
function webSocketOnClose(e){
    heartCheck.clear();
    isConnect = false; //断开后修改标识
    console.log(e)
    console.log('webSocket已经关闭 (code:' + e.code + ')')
    //被动断开,重新连接
    if(e.code == 1006){
        if(reConnectNum < 3){
            initWebSocket();
            ++reConnectNum;
        }else{
            v.$message({
                message: 'websocket连接不上,请刷新页面或联系开发人员!',
                type: 'warning'
            });
        }
    }
}

//连接发生错误的回调方法
function webSocketonError(e){
    heartCheck.clear();
    isConnect = false; //断开后修改标识
    console.log("WebSocket连接发生错误:");
    console.log(e);
}


//发送数据
function webSocketSend(data) {
    webSocket.send(JSON.stringify(data));//在这里根据自己的需要转换数据格式
}
//在其他需要socket地方主动关闭socket
function closeWebSocket(e) {
    webSocket.close();
    heartCheck.clear();
    isConnect = false;
    reConnectNum = 0;
}
//在其他需要socket地方接受数据
function getSock(callback) {
    globalCallback = callback
}
//在其他需要socket地方调用的函数,用来发送数据及接受数据
function sendSock(agentData) {
    //下面的判断主要是考虑到socket连接可能中断或者其他的因素,可以重新发送此条消息。
    switch (webSocket.readyState) {
        //CONNECTING:值为0,表示正在连接。
        case webSocket.CONNECTING:
            setTimeout(function() {
                sendSock(agentData, callback);
            }, 1000);
        break;
        //OPEN:值为1,表示连接成功,可以通信了。
        case webSocket.OPEN:
            webSocketSend(agentData);
        break;
        //CLOSING:值为2,表示连接正在关闭。
        case webSocket.CLOSING:
            setTimeout(function() {
                sendSock(agentData, callback);
            }, 1000);
        break;
        //CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
        case webSocket.CLOSED:
        // do something
        break;
        default:
        // this never happens
        break;
    }
}

export default {
  initWebSocket,
  closeWebSocket,
  sendSock,
  getSock
};

vue方法来自于这位大佬的文章,以下是链接。websocket封装_Paul_Chan_的博客-CSDN博客websocket封装https://blog.csdn.net/weixin_43422861/article/details/114259139?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168336616716782425125574%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168336616716782425125574&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-1-114259139-null-null.142%5Ev86%5Einsert_down28,239%5Ev2%5Einsert_chatgpt&utm_term=websocket%E5%B7%A5%E5%85%B7%E5%B0%81%E8%A3%85&spm=1018.2226.3001.4187

react代码

import React, { Component } from 'react';

class WebSocketHelper extends Component {
  constructor(props) {
    super(props);

    this.state = {
      websocket: null,
      heartBeatIntervalId: null,
    };
  }

  componentDidMount() {
    this.connectWebSocket();
  }

  componentWillUnmount() {
    this.closeWebSocket();
  }

  connectWebSocket = () => {
    const websocket = new WebSocket(this.props.url);

    websocket.onopen = () => {
      console.log('WebSocket connection opened.');
      this.props.onOpen && this.props.onOpen();

      if (this.props.heartBeatInterval) {
        const heartBeatIntervalId = setInterval(() => {
          console.log('Sending WebSocket heartbeat.');
          this.sendMessage(this.props.heartBeatMessage);
        }, this.props.heartBeatInterval);

        this.setState({ heartBeatIntervalId });
      }
    };

    websocket.onclose = () => {
      console.log('WebSocket connection closed.');
      this.props.onClose && this.props.onClose();

      if (this.state.heartBeatIntervalId) {
        clearInterval(this.state.heartBeatIntervalId);
        this.setState({ heartBeatIntervalId: null });
      }

      setTimeout(() => {
        console.log('Attempting to reconnect WebSocket.');
        this.connectWebSocket();
      }, this.props.reconnectInterval || 5000);
    };

    websocket.onerror = (error) => {
      console.error('WebSocket error:', error);
      this.props.onError && this.props.onError(error);
    };

    websocket.onmessage = (event) => {
      console.log('WebSocket message received:', event.data);
      this.props.onMessage && this.props.onMessage(event.data);
    };

    this.setState({ websocket });
  }

  closeWebSocket = () => {
    if (this.state.websocket) {
      this.state.websocket.close();
      console.log('WebSocket connection closed.');

      if (this.state.heartBeatIntervalId) {
        clearInterval(this.state.heartBeatIntervalId);
        this.setState({ heartBeatIntervalId: null });
      }
    }
  }

  sendMessage = (message) => {
    if (this.state.websocket) {
      console.log('Sending WebSocket message:', message);
      this.state.websocket.send(message);
    }
  }

  render() {
    return this.props.render({
      sendMessage: this.sendMessage,
      closeWebSocket: this.closeWebSocket,
    });
  }
}

export default WebSocketHelper;

使用

import React from 'react';
import WebSocketHelper from './WebSocketHelper';

function App() {
  const handleOpen = () => {
    console.log('WebSocket connection opened.');
  };

  const handleClose = () => {
    console.log('WebSocket connection closed.');
  };

  const handleError = (error) => {
    console.error('WebSocket error:', error);
  };

  const handleMessage = (message) => {
    console.log('WebSocket message received:', message);
  };

  const handleRender = ({ sendMessage, closeWebSocket }) => {
    // 这里可以使用 sendMessage 和 closeWebSocket 方法
    return (
      <div>
        <button onClick={() => sendMessage('Hello WebSocket!')}>Send Message</button>
        <button onClick={() => closeWebSocket()}>Close WebSocket</button>
      </div>
    );
  };

  return (
    <WebSocketHelper
      url="wss://example.com"
      onOpen={handleOpen}
      onClose={handleClose}
      onError={handleError}
      onMessage={handleMessage}
      render={handleRender}
    />
  );
}

export default App;

           更多详细信息详见官网:https://www.websocket.org/https://www.websocket.org/

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

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

相关文章

顺序表功能实现(入手版详解)

&#x1f349;博客主页&#xff1a;阿博历练记 &#x1f4d6;文章专栏&#xff1a;数据结构与算法 &#x1f69a;代码仓库&#xff1a;阿博编程日记 &#x1f339;欢迎关注&#xff1a;欢迎友友们点赞收藏关注哦 文章目录 &#x1f353;前言✨顺序表&#x1f50d;1.顺序表的整体…

【SpringBoot】SpringBoot 优雅地校验参数

1、为什么要校验参数&#xff1f; 在日常的开发中&#xff0c;为了防止非法参数对业务造成影响&#xff0c;需要对接口的参数进行校验&#xff0c;以便正确性地入库。 例如&#xff1a;登录时&#xff0c;就需要判断用户名、密码等信息是否为空。虽然前端也有校验&#xff0c;…

剑指offer 栈习题训练经验总结(未完)

第一题 定义栈的数据结构&#xff0c;请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中&#xff0c;调用 min、push 及 pop 的时间复杂度都是 O(1)。 class MinStack {private:stack<int> s;stack<int> min_s;public:void push(int x) {s.push(x);if…

xxl-job 集成 SpringBoot 使用

文章目录 前言xxl-job 集成 SpringBoot 使用1. xxl-job 安装部署超链接2. 启动xxl-job3. 集成 SpringBoot 使用3.1. 添加依赖3.2. 执行器 配置3.3. 执行器组件配置3.4. XxlJob 开发步骤 4. &#xff08;BEAN模式&#xff09;示例5. GLUE(Java) 示例6. 注意 前言 如果您觉得有用…

视觉震撼的数据可视化示例

众所周知&#xff0c;数据可以非常强大——当你真正理解它告诉你什么时。 数据和信息可视化(数据可视化或信息可视化)是对大量复杂的定量、定性数据、信息进行设计和创建易于沟通、易于理解的图形或视觉表示的实践&#xff0c;在静态、动态或交互式视觉项目的帮助下&#xff0…

Java对象的创建方式以及对象的引用

日子就是这么的庸常&#xff0c;却有细碎的事物&#xff0c;如太阳碎碎的光芒&#xff0c;洒落其上 Java创建对象有几种方式 new创建新对象 new创建我们就很熟悉了&#xff0c;像Person p new Person();等等 通过反射机制 这种创建对象的方式就是当我们编译时不知道要创…

java面试,redis面试,java面试大全

LEARNING_CONTENT 一个分布式锁的解决方案&#xff0c;另一个是分布式事务的解决方案 -2 flink 链接&#xff1a;flink参考文章 -1 linux of view 参考链接&#xff1a; linux常见面试题 linux查看占用cup最高的10个进程的命令&#xff1b; 参考文章&#xff1a;linux查看…

uboot 启动内核代码分析

0、uboot和内核区别 uboot的本质就是一个复杂点的裸机程序。内核本身也是一个"裸机程序“&#xff0c;和uboot、和其他裸机程序并没有本质区别。 区别就是操作系统运行起来后在软件上分为内核层和应用层&#xff0c;分层后两层的权限不同&#xff0c;在内存访问和设备操作…

iptables 防火墙进出控制

iptables 防火墙进出控制 iptables简介 iptables 是集成在 Linux 内核中的包过滤防火墙系统。使用 iptables 可以添加、删除具体的过滤规则&#xff0c;iptables 默认维护着 4 个表和 5 个链&#xff0c;所有的防火墙策略规则都被分别写入这些表与链中。 “四表”是指 iptab…

ES是如何解决高可用

https://www.cnblogs.com/crazymakercircle/p/15433680.html ES是一个分布式全文检索框架&#xff0c;隐藏了复杂的处理机制&#xff0c;核心数据分片机制、集群发现、分片负载均衡请求路由。 ES的高可用架构&#xff0c;总体如下图&#xff1a; 说明&#xff1a;本文会以pdf…

SQL 招聘网站岗位数据分析

数据清洗 1.删除包含空字段的行 create view v_data_clean_null as select * from data d where job_href is not null and job_href ! and job_name is not null and job_name ! and company_href is not null and company_href ! and company_name is not null and com…

OpenAI ChatGPT Unity接入

OpenAI ChatGPT Unity接入 OpenAI ChatGPT Unity接入OpenAi-API-Unity 方法OpenAi-API-Unity 下载本地配置Unity 模块URL接入gz 接入json 接入Open AIOpenAi-Api-Unity 插件文档 OpenAi 本地化接入 Unity 方法Unity 关键字识别语音合成 & 文字转语音音频记录 & 实时音频…

基于物联网及云计算技术的智慧充电桩平台设计方案

针对目前的充电桩监管难题&#xff0c;如何逐一击破各个痛点&#xff1f; TSINGSEE可提供基于"智能充电设备&#xff0b;云平台&#xff0b;APP小程序"一体化完整的解决方案&#xff0c;解决当前充电桩运营商面临的各种运营和管理难题。 一、方案介绍 方案充分利用…

容器技术的发展

容器技术的发展 近年来&#xff0c;随着计算机硬件、网络以及云计算等技术的迅速发展&#xff0c;云原生的概念也越来越受到业界人士的广泛关注&#xff0c;越来越多的应用场景开始拥抱云原生&#xff0c;其中容器技术的发展起着至关重要的作用。本章将介绍容器技术的基础知识…

瘦身必备!四款低卡美食狂掉20斤肥肉

夏天来了&#xff0c;想要减肥瘦身&#xff0c;却总是被高卡路里的食物所困扰&#xff1f;别担心&#xff0c;今天我为大家介绍四款低卡掉秤减脂美食&#xff0c;让你轻松享受美食的同时还能达到减肥的目的。 这四款美食简单易做&#xff0c;口感也十分好吃&#xff0c;适合各…

《花雕学AI》ChatGPT 的 Prompt 用法,不是随便写就行的,这 13 种才是最有效的

ChatGPT 是一款基于 GPT-3 模型的人工智能写作工具&#xff0c;它可以根据用户的输入和要求&#xff0c;生成各种类型和风格的文本内容&#xff0c;比如文章、故事、诗歌、对话、摘要等。ChatGPT 的强大之处在于它可以灵活地适应不同的写作场景和目的&#xff0c;只要用户给出合…

【STM32】定时器PWM模式详解

PWM模式&#xff1a; PWM模式1&#xff0c;向上计数时&#xff0c;PWM信号从有效电平变为无效电平 PWM模式2&#xff0c;向上计数时&#xff0c;PWM信号从无效电平变为有效电平 PWM极性&#xff1a; 极性为高时&#xff0c;高电平为有效电平&#xff0c;低电平为无效电平 极性…

【Android取证篇】Android设备USB调试打开方式(开发者模式)

【Android取证篇】Android设备USB调试打开方式(开发者模式) Android各个版本系统手机开启”USB调试”的入口不全相同&#xff0c;仅供参考—【蘇小沐】 1、【Android1.0-3.2】 路径&#xff1a;在应用列表选择「设置」->「应用程序」->「开发」->勾选「USB调试」选…

拿来吧你——一个类帮你搞定SpringBoot中的请求日志打印

拿来吧你——一个类帮你搞定SpringBoot中的请求日志打印 日常开发工作中避免不了要打印请求日志&#xff0c;这个功能几乎在所有的项目中都需要编写一次&#xff0c;重复的次数多了&#xff0c;难免会感觉繁琐&#xff0c;因此打算搞一个通用类把这块功能拆出来。 废话不多说—…

虹科方案|使用 HK-TRUENAS支持媒体和娱乐工作流程-1

一、摘要 开发和交付能够随时随地触及受众的媒体内容变得越来越重要和复杂。 在当今高度互联、娱乐驱动的世界中&#xff0c;媒体和娱乐 (M&E) 公司需要保持竞争力才能取得成功。 这些组织需要制作各种不同格式的信息和娱乐内容&#xff0c;以便在移动设备、台式机、工作站…