此号已经沉寂多时,似乎已经忘了上一次更新是什么时候了!这一次重拾旧爱,希望能够一直保持下去,坚持写作,快乐你我他

今天的主题是websocket,相信搞研发的兄弟对websocket并不陌生,都2020了别说自己还不知道,那都TM骗人。咱们的目标只有一个,那就是要搞懂它,下面就开始撸起袖子盘它!!!

现状

目前许多应用对数据实时更新要求很高。比如股票交易,数字资产交易,还有一些需要动态更新数据的大屏可视化应用等等。在HTML5面世前,动态实时更新数据的做法大多使用ajax定时轮询,或者长轮询来处理消息的实时推送。但是轮询的做法效率相当低,这样势必会较大程度浪费服务器和带宽资源,而我们接下来要讲的WebSocket正是来解决该问题而出现的,它可以使得B/S架构的应用拥有像C/S架构一样的实时通信能力

websocket简介

WebSocket 是 HTML5 新增的一种在单个 TCP 连接上进行全双工通讯的协议。诞生于2008年,在2011年成为国际标准。现在新版的所有浏览器都已经支持,但一些旧版本的浏览器兼容性就不是很好了

WebSocket的最大特点是:允许客户端和服务器之间进行全双工通信(即客户端可以向服务端推送数据,服务端也可以主动向客户端推送数据),以便任一方都可以通过建立的连接将数据推送到另一端,是真正的双向平等对话,属于服务器推送技术的一种WebSocket最新的协议是 13 RFC 6455

websocket特性

了解HTTP协议的童鞋应该都知道HTTP协议有以下两个突出的特性:其一:HTTP协议的通信只能由客户端发起,它无法实现服务器主动向客户端推送消息(单向请求)其二:HTTP协议是一种无状态的应用层协议,它采用的是请求/响应模型,发送请求得到响应连接关闭(生命周期结束)。每次通信都需要携带验证信息进行身份校验(耗时、耗资源、效率低)WebSocket可以说是在HTTP的基础上发明来的,改善了HTTP协议上面的两个特性。WebSocket只需要建立一次HTTP连接,就可以一直保持连接状态(如果两端长时间都没有通信也是会被关闭连接的 - 后面会讲到),此时已经是从HTTP协议升级到了WebSocket协议,后面的通信都是基于websocket协议。这相比于轮询方式的不停建立连接显然效率要大大提高http和websocket对比:

http和websocket协议及默认端口:

http和websocket都是建立在TCP协议之上:

WebSocket如何工作

Web浏览器和服务器都必须支持 WebSocket 协议来建立和维护连接。由于 WebSocket 连接长期存在,与典型的 HTTP 连接不同,对服务器有重要的影响客户端简单示例:

// 初始化实例var ws = new WebSocket("ws://echo.websocket.org");或者加密协议:var wss = new WebSocket("wss://echo.websocket.org");// 建立连接ws.onopen = function(evt) { console.log("连接建立成功,可以开始通信了...");   ws.send("Hello WebSocket!");};// 连接出错ws.onerror = function(evt) {console.log("连接出错 ...");};   // 消息监听ws.onmessage = function(evt) {console.log( "收到服务端消息: " + evt.data);  ws.close();};// 关闭连接ws.onclose = function(evt) {console.log("关闭连接 ...");};

Websocket客户端 API

1、WebSocket 构造函数WebSocket对象作为一个构造函数,用于新建WebSocket实例

var webSocket = new WebSocket('ws://localhost:8080');var webSockets = new WebSocket('wss://localhost:8080');

执行上面语句之后,客户端就会与服务器进行连接2、webSocket.readyStatereadyState属性,返回实例对象的当前状态,共有四种:CONNECTING:值为0,表示正在连接。OPEN:值为1,表示连接成功,可以通信了。CLOSING:值为2,表示连接正在关闭。CLOSED:值为3,表示连接已经关闭,或者打开连接失败。3、webSocket.bufferedAmountbufferedAmount属性,表示还有多少字节的二进制数据没有发送出去,可以用来判断发送是否结束

var data = new ArrayBuffer(10000000);webSocket.send(data);if (webSocket.bufferedAmount === 0) {      // 发送完毕} else {      // 发送还没结束}

4、webSocket.onopenonopen属性,用于指定连接成功后的回调函数

webSocket.onopen = function () {    webSocket.send('Hello Server!');}webSocket.addEventListener('open', function (event) {    webSocket.send('Hello Server!');});

5、webSocket.oncloseonclose属性,用于指定连接关闭后的回调函数

webSocket.onclose = function(event) {      var code = event.code;      var reason = event.reason;      var wasClean = event.wasClean;      // handle close event};webSocket.addEventListener("close", function(event) {      var code = event.code;      var reason = event.reason;      var wasClean = event.wasClean;      // handle close event});

6、webSocket.onmessageonmessage属性,用于指定收到服务器数据后的回调函数

webSocket.onmessage = function(event) {      var data = event.data;      // 处理数据};webSocket.addEventListener("message", function(event) {      var data = event.data;      // 处理数据});

注意:服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)

webSocket.onmessage = function(event){      if(typeof event.data === String) {            console.log("Received data string");      }      if(event.data instanceof ArrayBuffer){            var buffer = event.data;            console.log("Received arraybuffer");        }}

除了动态判断收到的数据类型,也可以使用binaryType属性,显式指定收到的二进制数据类型

// 收到的是 blob 数据webSocket.binaryType = "blob";webSocket.onmessage = function(e) {      console.log(e.data.size);};// 收到的是 ArrayBuffer 数据webSocket.binaryType = "arraybuffer";webSocket.onmessage = function(e) {      console.log(e.data.byteLength);};

7、webSocket.onerroronerror属性,用于指定报错时的回调函数

webSocket.onerror = function(event) {      // handle error event};webSocket.addEventListener("error", function(event) {      // handle error event});

8、webSocket.send()实例对象的send()方法用于向服务器发送数据发送文本的例子

webSocket.send('your message');

发送 Blob 对象的例子

var file = document.querySelector('input[type="file"]').files[0];webSocket.send(file);

发送 ArrayBuffer 对象的例子

// Sending canvas ImageData as ArrayBuffervar img = canvas_context.getImageData(0, 0, 400, 320);var binary = new Uint8Array(img.data.length);for (var i = 0; i < img.data.length; i++) {    binary[i] = img.data[i];}webSocket.send(binary.buffer);

9、webSocket.close()实例对象的close()方法用于向服务器关闭连接

webSocket.close()

服务端如何实现

WebSocket 在服务端的实现非常丰富。Node.js、Java、C++、Python 等多种语言都有自己的解决方案常用的 Node 实现有以下三种:µWebSocketsSocket.IOWebSocket-Node

WebSocket小结

HTTP 和 WebSocket 有什么关系?Websocket 其实是一个新的应用层协议,跟 HTTP 协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也可以说它是 HTTP 协议上的一种补充首先Websocket是基于HTTP协议的,或者说借用了HTTP的协议来完成一部分握手websocket握手阶段:

GET /chat HTTP/1.1Host: localhost:8080Origin: http://127.0.0.1:3000Connection: UpgradeUpgrade: websocketSec-WebSocket-Version: 13Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==Sec-WebSocket-Protocol: chat, superchat

Connection: Upgrade表示要升级协议Upgrade: websocket 表示要升级到websocket协议Sec-WebSocket-Version: 13表示websocket的版本,如果服务端不支持该版本,需要返回一个Sec-WebSocket-Version header,里面包含服务端支持的版本号Sec-WebSocket-Key:是一个Base64 encode的值,这个是浏览器随机生成的,与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接(Sec-WebSocket-Key,它由客户端生成并发给服务端,用于证明服务端接收到的是一个可受信的连接握手,可以帮助服务端排除自身接收到的由非 WebSocket 客户端发起的连接,该值是一串随机经过 base64 编码的字符串)Sec-WebSocket-Protocol:是一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议然后服务器会返回下列东西,表示已经接受到请求,成功建立Websocket啦!

HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=Sec-WebSocket-Protocol: chat

这里开始就是HTTP最后负责的区域了,告诉客户,我已经成功切换协议啦~Sec-WebSocket-Accept:这个则是经过服务器确认,根据客户端请求首部的Sec-WebSocket-Key计算出来的(Sec-WebSocket-Accept,服务端通过从客户端请求头中读取 Sec-WebSocket-Key 与一串全局唯一的标识字符串(俗称魔串)“258EAFA5-E914-47DA- 95CA-C5AB0DC85B11”做拼接,生成长度为160位的 SHA-1 字符串,然后进行 base64 编码,作为 Sec-WebSocket-Accept 的值回传给客户端)计算公式:1、将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。2、通过SHA1计算出摘要,并转成base64字符串toBase64(sha1(Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ) )Sec-WebSocket-Protocol:则是表示最终使用的协议至此,http已经完成它所有工作了,接下来就是完全按照Websocket协议进行通信了Sec-WebSocket-Key/Sec-WebSocket-Accept的主要作用在于提供基础的防护,减少恶意连接、意外连接:1、避免服务端收到非法的websocket连接(比如http客户端不小心请求连接websocket服务,此时服务端可以直接拒绝连接)2、确保服务端理解websocket连接。因为ws握手阶段采用的是http协议,因此可能ws连接是被一个http服务器处理并返回的,此时客户端可以通过Sec-WebSocket-Key来确保服务端认识ws协议。(并非百分百保险,比如总是存在那么些无聊的http服务器,光处理Sec-WebSocket-Key,但并没有实现ws协议。。。)3、用浏览器里发起ajax请求,设置header时,Sec-WebSocket-Key以及其他相关的header是被禁止的。这样可以避免客户端发送ajax请求时,意外请求协议升级(websocket upgrade)4、可以防止反向代理(不理解ws协议)返回错误的数据。比如反向代理前后收到两次ws连接的升级请求,反向代理把第一次请求的返回给cache住,然后第二次请求到来时直接把cache住的请求给返回(无意义的返回)5、Sec-WebSocket-Key主要目的并不是确保数据的安全性,因为Sec-WebSocket-Key、Sec-WebSocket-Accept的转换计算公式是公开的,而且非常简单,最主要的作用是预防一些常见的意外情况(非故意的)强调:Sec-WebSocket-Key/Sec-WebSocket-Accept 的换算,只能带来基本的保障,但连接是否安全、数据是否安全、客户端/服务端是否合法的 ws客户端、ws服务端,其实并没有实际性的保证websocket优点:1、支持双向通信,实时性更强。2、不用频繁送HTTP请求,只需要发送一个HTTP请求进行websocket握手,接下来则可以利用该TCP连接通过websocket协议通讯,避免了传输多个HTTP Header的浪费3、支持传输文本和二进制4、websocket数据传输是基于数据帧的,可以分片传输,不需要怕数据太大包容纳不下5、支持扩展。ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)WebSocket客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message)websocket出现之前的一些持久连接操作:1、长轮询:建立连接 -> 传输数据 -> 保持连接 -> 。。。-> 响应 -> 关闭连接采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果服务端没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。需要有很高的并发,也就是说同时接待客户的能力。(场地大小)服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护2、ajax轮询:建立连接 -> 传输数据 -> 响应 -> 关闭连接 -> 定时循环上面的过程定时向后台发请求,需要服务器有很快的处理速度和资源。(速度)请求中有大半是无用,浪费带宽和服务器资源3、长连接:建立连接 -> 传输数据 -> 保持连接 -> 传输数据 -> 。。。-> 关闭连接http1.0默认进行短连接,通过使用Connection: keep-alive进行长连接,http1.1默认进行持久连接。在一次 TCP 连接中可以完成多个 http 请求,但是对每个请求仍然要单独发 header,keep-alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Nginx\Apache)中设定这个时间启用keep-alive模式会更高效,性能更高。因为避免了建立/释放连接的开销以上持久连接的缺点:1、被动性 - 只能由客户端发送请求2、在传统的方式上,要不断的建立和关闭连接,由于http是非状态性的,每次都要重新传输identity info(鉴别信息),来告诉服务端你是谁,解析耗时,耗资源,效率还低3、http1.1串行单线程处理,响应是有顺序的,只有上一个请求完成后,下一个才能响应。一旦有任务处理超时等,后续任务只能被阻塞(线头阻塞)4、keep-alive双方并没有建立正真的连接会话,服务端可以在任何一次请求完成后关闭websocket长时间没有通信会自动断开的原因?利用nginx代理websocket的时候,发现客户端和服务器握手成功后,如果在60s时间内没有数据交互,连接就会自动断开nginx.conf 文件里location 中的proxy_read_timeout 默认60s断开保持持久连接的做法:1、把服务器的默认时间改大 + 发送心跳机制2、定时检测客户端是否已经断开连接,断开重连构建打包工具Rollup.js入门指南使用React的注意点(一)你不可不知道的React生命周期强推一款临时邮件神器

c++ websocket客户端_你要的websocket都在这,收好不谢~~~相关推荐

  1. c++ websocket客户端_阿里面经WebSocket实时通信

    一.websocket概述 1.随着互联网的快速发展,程序员需要处理的业务场景也越来越多了,ajax对于一些常链接实时刷新数据特殊的场景的处理就显的很无力,于是webSocket出现了. 2.HTTP ...

  2. spring boot websocket 客户端_Spring Boot 开发集成 WebSocket,实现私有即时通信系统

    ###1/ 概述 利用Spring Boot作为基础框架,Spring Security作为安全框架,WebSocket作为通信框架,实现点对点聊天和群聊天. ###2/ 所需依赖 Spring Bo ...

  3. python websocket爬虫_详解python websocket获取实时数据的几种常见链接方式

    第一种, 使用create_connection链接,需要pip install websocket-client (此方法不建议使用,链接不稳定,容易断,并且连接很耗时) import time f ...

  4. java websocket广播_使用 Spring 对 Websocket 进行简单的消息广播和单播

    最近在做毕业设计,需要用到 Websocket 实现消息的推送. 在 Spring 官网上查看文档,发现 Spring 对 Websocket 的功能进行了太多扩展,引入了 STOMP 和 Broke ...

  5. e5cc温控仪通讯参数设定_自动化工程师:施耐德 PLC常见两种编程通讯控制实例,收好不谢...

    1.第一种是采用 UNTLW1协议进行联机编程: 参数设置与通讯配置检查:用 Premium的专用编程电缆"TSXPCX3030-C(USB接口,有专门的驱动)"通过调试机与CPU ...

  6. python与施耐德plc通讯_自动化工程师:施耐德 PLC常见两种编程通讯控制实例,收好不谢...

    1.第一种是采用 UNTLW1协议进行联机编程: 参数设置与通讯配置检查:用 Premium的专用编程电缆"TSXPCX3030-C(USB接口,有专门的驱动)"通过调试机与CPU ...

  7. 火币网行情获取的websocket客户端

    从验证结果看应该是网络关闭了,不过程序写的不错,可以作为其它websocket客户端的测试程序 # !/usr/bin/env python # -*- coding: utf-8 -*- # aut ...

  8. java编写websocket客户端

    前言 webSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据. 本次介绍的是websocket客户端的编写,至于websocket服务端的编写可以看我之前写的 ...

  9. ESP32 单片机学习笔记 - 08 - WebSocket客户端

    前言,终于要到网络模型的最后一层,第四层,应用层,http.websocket的实践了. 文章目录 ESP32 单片机学习笔记 - 08 - WebSocket客户端 一.应用层协议 科普概念 二.编 ...

最新文章

  1. mysql 远程连接速度慢的解决方案
  2. 基于zxing生成与解析二维码、条形码
  3. MVC路由学习:自定义路由参数(用户看不到参数名),重新定义路由规则
  4. 答应我不要问TCP三次握手四次挥手
  5. 写一个使两个整数进行交换的方法(不能使用临时变量) 【前端每日一题-27】...
  6. python单例_Python - 单例模式(Singleton)
  7. LeCun:放弃深度学习吧,AI的未来是能量学习
  8. shell下后台挂起
  9. 低代码工具让人人都是程序员?别再吐槽了,它能做这些事
  10. 在线文本转2-36任意进制工具
  11. Python文件输入输出
  12. 一分钟了解微服务的好处和陷阱
  13. JAVA Map集合类简介
  14. 基于EEGLAB的脑电数据预处理
  15. 【Android】ListView刷新、加载
  16. 5G:认识5G关键技术
  17. 雷达波位编排matlab仿真
  18. windows启动时自动运行程序四种方法(登录或不登录都可以的)
  19. 超级AI大脑:全能型学习助理
  20. 如何判断img加载完成?

热门文章

  1. 卷积神经网络(CNN)前向传播算法
  2. Matlab 自带机器学习算法汇总
  3. MATLAB基本操作(四):结构体struct元胞数组cell
  4. 深度学习100例-卷积神经网络(CNN)3D医疗影像识别 | 第23天
  5. java的main函数为什么是public static void main(String[] args)
  6. 阿里云制造行业总经理胡鑫:中台技术如何支撑企业数字化转型
  7. 大众点评订单分库分表实践之路
  8. spring源码分析之freemarker整合
  9. Catch Me If You ... Can't Do Otherwise--转载
  10. ios--成员变量与属性的区别