WebSocket 与 Socket.IO-程序员宅基地

技术标签: ViewUI  网络  javascript  

WebSocket 与 Socket.IO

最近小组在做一个智慧交通的项目,其中有个 “分享屏幕” 的功能,即一个 client 能够将自己当前的页面分享到另外一个 client,针对这个需求,我们利用了 WebSocket 技术,具体说是 Socket.IO。

1. 什么是 WebSocket

提到 WebSocket,我首先会想到 “及时通讯” 和 “推送” 这类词。在 WebSocket 以前,很多网站通过其他方式来推送信息,下面我们先看看以前的推送方式,这样,有比较才能看出 WebSocket 的优势。

1.1 (短)轮询(Polling)

这种方式下,client 每隔一段时间都会向 server 发送 http 请求,服务器收到请求后,将最新的数据发回给 client。一开始必须通过提交表单的形式,这样的后果就是传输很多冗余的数据,浪费了带宽。后来 Ajax 出现,减少了传输数据量。

如图所示,在 client 向 server 发送一个请求活动结束后,server 中的数据发生了改变,所以 client 向 server 发送的第二次请求中,server 会将最新的数据返回给 client。

但这种方式也存在弊端。比如在某个时间段 server 没有更新数据,但 client 仍然每隔一段时间发送请求来询问,所以这段时间内的询问都是无效的,这样浪费了网络带宽。将发送请求的间隔时间加大会缓解这种浪费,但如果 server 更新数据很快时,这样又不能满足数据的实时性。

1.2 Comet

鉴于(短)轮询的弊端,一种基于 HTTP 长连接的 “服务器推” 的技术被 hack 了出来,这种技术被命名为 Comet。其与(短)轮询主要区别就是,在轮询方式下,要想取得数据,必须首先发送请求,在实时性要求较高的情况下,只能增加向 server 请求的频率;而 Comet 则不同,client 与 server 端保持一个长连接,只有数据发生改变时,server 才主动将数据推送给 client。Comet 又可以被细分为两种实现方式,一种是长轮询机制,一种是流技术。

1.2.1 长轮询(Long-polling)

client 向 server 发出请求,server 接收到请求后,server 并不一定立即发送回应给 client,而是看数据是否更新,如果数据已经更新了的话,那就立即将数据返回给 client;但如果数据没有更新,那就把这个请求保持住,等待有新的数据到来时,才将数据返回给 client。

当然了,如果 server 的数据长时间没有更新,一段时间后,请求便会超时,client 收到超时信息后,再立即发送一个新的请求给 server。

如图所示,在长轮询机制下,client 向 server 发送了请求后,server会等数据更新完才会将数据返回,而不是像(短)轮询一样不管数据有没有更新然后立即返回。

这种方式也有弊端。当 server 向 client 发送数据后,必须等待下一次请求才能将新的数据发送出去,这样 client 接收到新数据的间隔最短时间便是 2 * RTT(往返时间),这样便无法应对 server 端数据更新频率较快的情况。

1.2.2 流技术(Http Streaming)

流技术基于 Iframe。Iframe 是 HTML 标记,这个标记的 src 属性会保持对指定 server 的长连接请求,server 就可以不断地向 client 返回数据。

可以看出,流技术与长轮询的区别是长轮询本质上还是一种轮询方式,只不过连接的时间有所增加,想要向 server 获取新的数据,client 只能一遍遍的发送请求;而流技术是一直保持连接,不需要 client 请求,当数据发生改变时,server 自动的将数据发送给 client。

如图所示,client 与 server 建立连接之后,便不会断开。当数据发生变化,server 便将数据发送给 client。

但这种方式有一个明显的不足之处,网页会一直显示未加载完成的状态,虽然我没有强迫症,但这点还是难以忍受。

1.3 WebSocket

写到现在,大家会发现,前人推出那么多的解决方案,想要解决的唯一的问题便是怎么让 server 将最新的数据以最快的速度发送给 client。但 HTTP 是个懒惰的协议,server 只有收到请求才会做出回应,否则什么事都不干。因此,为了彻底解决这个 server 主动向 client 发送数据的问题,W3C 在 HTML5 中提供了一种 client 与 server 间进行全双工通讯的网络技术 WebSocket。WebSocket 是一个全新的、独立的协议,基于 TCP 协议,与 HTTP 协议兼容却不会融入 HTTP 协议,仅仅作为 HTML5 的一部分。

那 WebSocket 与 HTTP 什么关系呢?简单来说,WebSocket 是一种协议,是一种与 HTTP 同等的网络协议,两者都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

WebSocket 原理

相比于传统 HTTP 的每次“请求-应答”都要 client 与 server 建立连接的模式,WebSocket 是一种长连接的模式。具体什么意思呢?就是一旦 WebSocket 连接建立后,除非 client 或者 server 中有一端主动断开连接,否则每次数据传输之前都不需要 HTTP 那样请求数据。从上面的图可以看出,client 第一次需要与 server 建立连接,当 server 确认连接之后,两者便一直处于连接状态。直到一方断开连接,WebSocket 连接才断开。

下面我们从报文层面谈一下 WebSocket 与 HTTP 的差异。

首先,client 发起 WebSocket 连接,报文类似于 HTTP,但主要有几点不一样的地方:

  • "Upgrade: websocket": 表明这是一个 WebSocket 类型请求,意在告诉 server 需要将通信协议切换到 WebSocket

  • "Sec-WebSocket-Key: *": 是 client 发送的一个 base64 编码的密文,要求 server 必须返回一个对应加密的 "Sec-WebSocket-Accept" 应答,否则 client 会抛出 "Error during WebSocket handshake" 错误,并关闭连接

server 收到报文后,如果支持 WebSocket 协议,那么就会将自己的通信协议切换到 WebSocket,返回以下信息:

  • "HTTP/1.1 101 WebSocket Protocol Handshake":返回的状态码为 101,表示同意 client 的协议转换请求

  • "Upgrade: websocket"

  • "Connection: Upgrade"

  • "Sec-WebSocket-Accept: *"

  • ...

以上都是利用 HTTP 协议完成的。这样,经过“请求-相应”的过程, server 与 client 的 WebSocket 连接握手成功,后续便可以进行 TCP 通讯了,也就没有 HTTP 什么事了。可以查阅WebSocket 协议栈了解 WebSocket 的 client 与 server 更详细的交互数据格式。

WebSocket 与 Socket

网络应用中,两个应用程序同时需要向对方发送消息的能力(即全双工通信),所利用到的技术就是 socket,其能够提供端对端的通信。对于程序员而言,其需要在 A 端创建一个 socket 实例,并为这个实例提供其所要连接的 B 端的 IP 地址和端口号,而在 B 端创建另一个 socket 实例,并且绑定本地端口号来进行监听。当 A 和 B 建立连接后,双方就建立了一个端对端的 TCP 连接,从而可以进行双向通信。

WebSocekt 是 HTML5 规范中的一部分,其借鉴了 socket 的思想,为 client 和 server 之间提供了类似的双向通信机制。同时,WebSocket 又是一种新的应用层协议,包含一套标准的 API;而 socket 并不是一个协议,而是一组接口,其主要方便大家直接使用更底层的协议(比如 TCP 或 UDP)

什么是 Socket.IO

Socket.IO 是一个封装了 Websocket、基于 Node 的 JavaScript 框架,包含 client 的 JavaScript 和 server 的 Node。其屏蔽了所有底层细节,让顶层调用非常简单。

另外,Socket.IO 还有一个非常重要的好处。其不仅支持 WebSocket,还支持许多种轮询机制以及其他实时通信方式,并封装了通用的接口。这些方式包含 Adobe Flash Socket、Ajax 长轮询、Ajax multipart streaming 、持久 Iframe、JSONP 轮询等。换句话说,当 Socket.IO 检测到当前环境不支持 WebSocket 时,能够自动地选择最佳的方式来实现网络的实时通信。

参考:

  1. Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

  2. 微信公众号: 【龙果】 --- 《WebSocket --web持久连接神器》

  3. WebSocket详解(一):初步认识WebSocket技术

  4. Socket 与 WebSocket

  5. Differences between socket.io and websockets

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34401479/article/details/89279878

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法