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


    目录

    一、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事件:

    1. socket.addEventListener('open', (event) => {
    2. console.log('WebSocket连接已打开');
    3. });
    4. socket.addEventListener('message', (event) => {
    5. console.log('接收到消息:', event.data);
    6. });
    7. socket.addEventListener('error', (event) => {
    8. console.log('WebSocket连接出错:', event);
    9. });
    10. socket.addEventListener('close', (event) => {
    11. console.log('WebSocket连接已关闭');
    12. });

    第三步

            发送数据。可以使用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的缓冲区中,直到网络层可以接受这些数据时再发送出去。

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

    WebSocket.extensions

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

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

    WebSocket.binaryType

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

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

    三、Websocket的封装

    vue代码

    1. import Vue from 'vue'
    2. import { Message } from 'element-ui'
    3. let v = new Vue()
    4. v.$message = Message;
    5. var webSocket = null;
    6. var isConnect = false; //连接状态
    7. var globalCallback = function(e){ console.log(e) };//定义外部接收数据的回调函数
    8. var reConnectNum = 0;//重连次数
    9. var websocketUrl = process.env.VUE_APP_API_WEBSOCKET_URL;
    10. //心跳设置
    11. var heartCheck = {
    12. heartbeatData:{
    13. DevID:{
    14. value:Vue.ls.get('devid')
    15. },
    16. DevHeart:{
    17. value:"1"
    18. }
    19. },//心跳包
    20. timeout: 60 * 1000, //每段时间发送一次心跳包 这里设置为60s
    21. heartbeat: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)
    22. start: function () {
    23. this.heartbeat = setInterval(()=>{
    24. if (isConnect){
    25. webSocketSend(this.heartbeatData);
    26. }else{
    27. this.clear();
    28. }
    29. }, this.timeout);
    30. },
    31. reset: function () {
    32. clearInterval(this.heartbeat);
    33. this.start();
    34. },
    35. clear:function(){
    36. clearInterval(this.heartbeat);
    37. }
    38. }
    39. //初始化websocket
    40. function initWebSocket(callback) {
    41. //此callback为在其他地方调用时定义的接收socket数据的函数
    42. if(callback){
    43. if(typeof callback == 'function'){
    44. globalCallback = callback
    45. }else{
    46. throw new Error("callback is not a function")
    47. }
    48. }
    49. if ("WebSocket" in window) {
    50. webSocket = new WebSocket(websocketUrl);//创建socket对象
    51. } else {
    52. Message({
    53. message: '该浏览器不支持websocket!',
    54. type: 'warning'
    55. });
    56. return
    57. }
    58. //打开
    59. webSocket.onopen = function() {
    60. webSocketOpen();
    61. };
    62. //收信
    63. webSocket.onmessage = function(e) {
    64. webSocketOnMessage(e);
    65. };
    66. //关闭
    67. webSocket.onclose = function(e) {
    68. webSocketOnClose(e);
    69. };
    70. //连接发生错误的回调方法
    71. webSocket.onerror = function(e) {
    72. webSocketonError(e);
    73. };
    74. }
    75. //连接socket建立时触发
    76. function webSocketOpen() {
    77. console.log("WebSocket连接成功");
    78. //首次握手
    79. webSocketSend(heartCheck.heartbeatData);
    80. isConnect = true;
    81. heartCheck.start();
    82. reConnectNum = 0;
    83. }
    84. //客户端接收服务端数据时触发,e为接受的数据对象
    85. function webSocketOnMessage(e) {
    86. console.log("websocket信息:");
    87. console.log(e.data)
    88. const data = JSON.parse(e.data);//根据自己的需要对接收到的数据进行格式化
    89. globalCallback(data);//将data传给在外定义的接收数据的函数,至关重要。
    90. }
    91. //socket关闭时触发
    92. function webSocketOnClose(e){
    93. heartCheck.clear();
    94. isConnect = false; //断开后修改标识
    95. console.log(e)
    96. console.log('webSocket已经关闭 (code:' + e.code + ')')
    97. //被动断开,重新连接
    98. if(e.code == 1006){
    99. if(reConnectNum < 3){
    100. initWebSocket();
    101. ++reConnectNum;
    102. }else{
    103. v.$message({
    104. message: 'websocket连接不上,请刷新页面或联系开发人员!',
    105. type: 'warning'
    106. });
    107. }
    108. }
    109. }
    110. //连接发生错误的回调方法
    111. function webSocketonError(e){
    112. heartCheck.clear();
    113. isConnect = false; //断开后修改标识
    114. console.log("WebSocket连接发生错误:");
    115. console.log(e);
    116. }
    117. //发送数据
    118. function webSocketSend(data) {
    119. webSocket.send(JSON.stringify(data));//在这里根据自己的需要转换数据格式
    120. }
    121. //在其他需要socket地方主动关闭socket
    122. function closeWebSocket(e) {
    123. webSocket.close();
    124. heartCheck.clear();
    125. isConnect = false;
    126. reConnectNum = 0;
    127. }
    128. //在其他需要socket地方接受数据
    129. function getSock(callback) {
    130. globalCallback = callback
    131. }
    132. //在其他需要socket地方调用的函数,用来发送数据及接受数据
    133. function sendSock(agentData) {
    134. //下面的判断主要是考虑到socket连接可能中断或者其他的因素,可以重新发送此条消息。
    135. switch (webSocket.readyState) {
    136. //CONNECTING:值为0,表示正在连接。
    137. case webSocket.CONNECTING:
    138. setTimeout(function() {
    139. sendSock(agentData, callback);
    140. }, 1000);
    141. break;
    142. //OPEN:值为1,表示连接成功,可以通信了。
    143. case webSocket.OPEN:
    144. webSocketSend(agentData);
    145. break;
    146. //CLOSING:值为2,表示连接正在关闭。
    147. case webSocket.CLOSING:
    148. setTimeout(function() {
    149. sendSock(agentData, callback);
    150. }, 1000);
    151. break;
    152. //CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
    153. case webSocket.CLOSED:
    154. // do something
    155. break;
    156. default:
    157. // this never happens
    158. break;
    159. }
    160. }
    161. export default {
    162. initWebSocket,
    163. closeWebSocket,
    164. sendSock,
    165. getSock
    166. };

    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代码

    1. import React, { Component } from 'react';
    2. class WebSocketHelper extends Component {
    3. constructor(props) {
    4. super(props);
    5. this.state = {
    6. websocket: null,
    7. heartBeatIntervalId: null,
    8. };
    9. }
    10. componentDidMount() {
    11. this.connectWebSocket();
    12. }
    13. componentWillUnmount() {
    14. this.closeWebSocket();
    15. }
    16. connectWebSocket = () => {
    17. const websocket = new WebSocket(this.props.url);
    18. websocket.onopen = () => {
    19. console.log('WebSocket connection opened.');
    20. this.props.onOpen && this.props.onOpen();
    21. if (this.props.heartBeatInterval) {
    22. const heartBeatIntervalId = setInterval(() => {
    23. console.log('Sending WebSocket heartbeat.');
    24. this.sendMessage(this.props.heartBeatMessage);
    25. }, this.props.heartBeatInterval);
    26. this.setState({ heartBeatIntervalId });
    27. }
    28. };
    29. websocket.onclose = () => {
    30. console.log('WebSocket connection closed.');
    31. this.props.onClose && this.props.onClose();
    32. if (this.state.heartBeatIntervalId) {
    33. clearInterval(this.state.heartBeatIntervalId);
    34. this.setState({ heartBeatIntervalId: null });
    35. }
    36. setTimeout(() => {
    37. console.log('Attempting to reconnect WebSocket.');
    38. this.connectWebSocket();
    39. }, this.props.reconnectInterval || 5000);
    40. };
    41. websocket.onerror = (error) => {
    42. console.error('WebSocket error:', error);
    43. this.props.onError && this.props.onError(error);
    44. };
    45. websocket.onmessage = (event) => {
    46. console.log('WebSocket message received:', event.data);
    47. this.props.onMessage && this.props.onMessage(event.data);
    48. };
    49. this.setState({ websocket });
    50. }
    51. closeWebSocket = () => {
    52. if (this.state.websocket) {
    53. this.state.websocket.close();
    54. console.log('WebSocket connection closed.');
    55. if (this.state.heartBeatIntervalId) {
    56. clearInterval(this.state.heartBeatIntervalId);
    57. this.setState({ heartBeatIntervalId: null });
    58. }
    59. }
    60. }
    61. sendMessage = (message) => {
    62. if (this.state.websocket) {
    63. console.log('Sending WebSocket message:', message);
    64. this.state.websocket.send(message);
    65. }
    66. }
    67. render() {
    68. return this.props.render({
    69. sendMessage: this.sendMessage,
    70. closeWebSocket: this.closeWebSocket,
    71. });
    72. }
    73. }
    74. export default WebSocketHelper;

    使用

    1. import React from 'react';
    2. import WebSocketHelper from './WebSocketHelper';
    3. function App() {
    4. const handleOpen = () => {
    5. console.log('WebSocket connection opened.');
    6. };
    7. const handleClose = () => {
    8. console.log('WebSocket connection closed.');
    9. };
    10. const handleError = (error) => {
    11. console.error('WebSocket error:', error);
    12. };
    13. const handleMessage = (message) => {
    14. console.log('WebSocket message received:', message);
    15. };
    16. const handleRender = ({ sendMessage, closeWebSocket }) => {
    17. // 这里可以使用 sendMessage 和 closeWebSocket 方法
    18. return (
    19. <div>
    20. <button onClick={() => sendMessage('Hello WebSocket!')}>Send Messagebutton>
    21. <button onClick={() => closeWebSocket()}>Close WebSocketbutton>
    22. div>
    23. );
    24. };
    25. return (
    26. <WebSocketHelper
    27. url="wss://example.com"
    28. onOpen={handleOpen}
    29. onClose={handleClose}
    30. onError={handleError}
    31. onMessage={handleMessage}
    32. render={handleRender}
    33. />
    34. );
    35. }
    36. export default App;

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

  • 相关阅读:
    存储器、I/O组织、微处理器
    MacOS安装java.安装openjdk步骤
    openstack 业务组件安装
    matlab查找符号表达式中的符号变量
    从 0 到 1,开发一个智能问答机器人
    Ngnix 部署 结束顽固进程
    vscode使用ssh连接远程Ubuntu服务器(记录)
    用57000字讲解完2022年Java岗面试最常问的100道题,太肝了
    Samba服务搭建
    EtherCAT主站IgH解析(二)-- 如何将Igh移植到Linux/Windows/RTOS等多操作系统
  • 原文地址:https://blog.csdn.net/qq_45799465/article/details/130532631