关于WebSocket_彪彪_的博客-程序员宅基地

技术标签: 向大佬学习  WebSocket  

原文来自廖雪峰老师的博客 链接:https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096
WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。

为什么传统的HTTP协议不能做到WebSocket实现的功能?这是因为HTTP协议是一个请求-响应协议,请求必须先由浏览器发给服务器,服务器才能响应这个请求,再把数据发送给浏览器。换句话说,浏览器不主动请求,服务器是没法主动发数据给浏览器的。

这样一来,要在浏览器中搞一个实时聊天,在线炒股(不鼓励),或者在线多人游戏的话就没法实现了,只能借助Flash这些插件。

也有人说,HTTP协议其实也能实现啊,比如用轮询或者Comet。轮询是指浏览器通过JavaScript启动一个定时器,然后以固定的间隔给服务器发请求,询问服务器有没有新消息。这个机制的缺点一是实时性不够,二是频繁的请求会给服务器带来极大的压力。

Comet本质上也是轮询,但是在没有消息的情况下,服务器先拖一段时间,等到有消息了再回复。这个机制暂时地解决了实时性问题,但是它带来了新的问题:以多线程模式运行的服务器会让大部分线程大部分时间都处于挂起状态,极大地浪费服务器资源。另外,一个HTTP连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能关闭这个连接,而网关是我们不可控的,这就要求Comet连接必须定期发一些ping数据表示连接“正常工作”。

以上两种机制都治标不治本,所以,HTML5推出了WebSocket标准,让浏览器和服务器之间可以建立无限制的全双工通信,任何一方都可以主动发消息给对方。

WebSocket协议

WebSocket并不是全新的协议,而是利用了HTTP协议来建立连接。我们来看看WebSocket连接是如何创建的。

首先,WebSocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

该请求和普通的HTTP请求有几点不同:

GET请求的地址不是类似/path/,而是以ws://开头的地址;
请求头Upgrade: websocket和Connection: Upgrade表示这个连接将要被转换为WebSocket连接;
Sec-WebSocket-Key是用于标识这个连接,并非用于加密数据;
Sec-WebSocket-Version指定了WebSocket的协议版本。
随后,服务器如果接受该请求,就会返回如下响应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string
该响应代码101表示本次连接的HTTP协议即将被更改,更改后的协议就是Upgrade: websocket指定的WebSocket协议。

版本号和子协议规定了双方能理解的数据格式,以及是否支持压缩等等。如果仅使用WebSocket的API,就不需要关心这些。

现在,一个WebSocket连接就建立成功,浏览器和服务器就可以随时主动发送消息给对方。消息有两种,一种是文本,一种是二进制数据。通常,我们可以发送JSON格式的文本,这样,在浏览器处理起来就十分容易。

为什么WebSocket连接可以实现全双工通信而HTTP连接不行呢?实际上HTTP协议是建立在TCP协议之上的,TCP协议本身就实现了全双工通信,但是HTTP协议的请求-应答机制限制了全双工通信。WebSocket连接建立以后,其实只是简单规定了一下:接下来,咱们通信就不使用HTTP协议了,直接互相发数据吧。

安全的WebSocket连接机制和HTTPS类似。首先,浏览器用wss://xxx创建WebSocket连接时,会先通过HTTPS创建安全的连接,然后,该HTTPS连接升级为WebSocket连接,底层通信走的仍然是安全的SSL/TLS协议。

浏览器

很显然,要支持WebSocket通信,浏览器得支持这个协议,这样才能发出ws://xxx的请求。目前,支持WebSocket的主流浏览器如下:

Chrome
Firefox
IE >= 10
Sarafi >= 6
Android >= 4.4
iOS >= 8

服务器

由于WebSocket是一个协议,服务器具体怎么实现,取决于所用编程语言和框架本身。Node.js本身支持的协议包括TCP协议和HTTP协议,要支持WebSocket协议,需要对Node.js提供的HTTPServer做额外的开发。已经有若干基于Node.js的稳定可靠的WebSocket实现,我们直接用npm安装使用即可。

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

智能推荐

深度学习与计算机视觉系列(3)_线性SVM与SoftMax分类器_龙心尘的博客-程序员宅基地

这个部分我们介绍一类新的分类器方法,而对其的改进和启发也能帮助我们自然而然地过渡到深度学习中的卷积神经网。有两个重要的概念:得分函数/score function:将原始数据映射到每个类的打分的函数损失函数/loss function:用于量化模型预测结果和实际结果之间吻合度的函数在我们得到损失函数之后,我们就将问题转化成为一个最优化的问题,目标是得到让我们的损失函数取值最小的一组参数。

FS_S5PC100平台上Linux Camera驱动开发详解_Angelia_cfq的博客-程序员宅基地

FS_S5PC100平台上Linux Camera驱动开发详解作者:刘老师,华清远见嵌入式学院讲师。说明:        理解摄像头驱动需要四个前提:        1)摄像头基本的工作原理和S5PC100集成的Camera控制器的工作原理        2)platform_device和platform_driver工作原理        3)Linux内核V4L2驱动

嵌入式开发学习框架_Mzcc_bbms的博客-程序员宅基地

嵌入式开发学习框架嵌入式定义传统定义:是以应用为中心,以计算机技术为基础,并且硬件可裁剪,适用于应用系统对功能、可靠性、成本、体积、功耗 严格要求的专用计算机系统。客观定义:除PC之外的一切计算机系统。学习路线思考嵌入式与物联网、云计算、大数据的关系?...

ABP学习实践(十六)--领域驱动设计(DDD)回顾_ludewig的博客-程序员宅基地

ABP框架并没有实现领域驱动设计(DDD)的所有思想,但是并不妨碍用领域驱动的思想去理解ABP库框架。1.领域驱动设计(DDD)与微服务(MicroService)的关系?2.领域驱动设计(DDD)

mui js集成个推 推送消息到通知栏,点击通知栏跳转到指定的页面_baidu_24743861的博客-程序员宅基地

/** * 消息推送 */document.addEventListener("plusready", function() { // 监听点击消息事件 plus.push.addEventListener("click", function(msg) { //根据需要填写 //type为0-问题 1-应急 var payLoad = msg.payload; v...

[Deep learning 环境配置之一]win10 + python 3.6 + Anaconda+ 安装 opencv3.4.3:解决import cv2 问题_Chaser_LittleBee的博客-程序员宅基地

win10 + python 3.6 + Anaconda+ 安装 opencv3.4.3:解决import cv2 问题OpenCV是一个图像处理的经典库,而且关键是一直在升级。为了在Python中调用opencv,特别是看到好多代码都是import cv2,而这个在python中是无法直接进行pip install安装的,也没办法用 conda list 安装。 查了下,才知道需要从op...

随便推点

Apache服务器默认配置的一些基本信息_Tony0520.的博客-程序员宅基地

配置文件:/etc/httpd/conf/http.conf1)"/etc/httpd/conf主要存放了配置文件httpd.conf,这个是最重要的配置文件,Apache的所有主要权限和功能都在这个文件中进行了详细的设置。 (2) "/etc/httpd/conf.d" 里面存放的是一些额外的参数档,比如php.conf,或者一些自己设定的额外参数等信息。这个目录最大的好处就

git常用命令总结_weixin_30823833的博客-程序员宅基地

一、 Git 常用命令速查git branch 查看本地所有分支git status 查看当前状态git commit 提交git branch -a 查看所有的分支git branch -r 查看远程所有分支git commit -am "init" 提交并且加注释git remote add origin [email protected]:ndshowgit push ori...

centos下安装MySQL-python_feifeilyj的博客-程序员宅基地

1) 下载MySQL-pythonwget https://pypi.python.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip#md5=654f75b302db6ed8dc5a898c625e030c2) 解压缩unz

JavaScript的组成部分之操作对象与表单_I'm sure ok!的博客-程序员宅基地

文章目录1.JavaScript的组成部分2.操作BOM对象1).Window2).Navigato(导航)3).screen4).location5).document6).history3.操作DOM对象1).获得dom节点1.JavaScript的组成部分javascript组成一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:核心(ECMAScript)、文档对象模...

远程服务调用之RMI、Hessian、Burlap、Spring的HTTPinvoker_tomoto_zh的博客-程序员宅基地

RMI:在服务端,使用RmiServiceExporter把POJO包装到RMI服务适配器中,并将服务适配器绑定到RMI注册表中,从而将POJO转换为RMI服务,在客户端,RMI服务将远程服务使用一个代理装配进来,使得我们可以像使用本地服务一样使用远程服务;它使用二进制协议,使用Java标准的对象序列化机制,只能服务于Java服务。Hessian、Burlap:Hessian和Burlap一样

python读取ini文件所有节点,使用Python将ini文件中的所有内容读入字典_乔安娜Joanna的博客-程序员宅基地

Normally, I code as follows for getting a particular item in a variable as followstry:config = ConfigParser.ConfigParser()config.read(self.iniPathName)except ConfigParser.MissingSectionHeaderError, e:...

推荐文章

热门文章

相关标签