欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

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

发布时间:2025/3/21 90 豆豆
生活随笔 收集整理的这篇文章主要介绍了 c++ websocket客户端_你要的websocket都在这,收好不谢~~~ 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
此号已经沉寂多时,似乎已经忘了上一次更新是什么时候了!这一次重拾旧爱,希望能够一直保持下去,坚持写作,快乐你我他

今天的主题是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, superchatConnection: 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都在这,收好不谢~~~的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。