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

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签