WebSocket原理与实践(二)---WebSocket协议
WebSocket原理与实践(二)---WebSocket协议
WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的。协议定义ws和wss协议,分别为普通请求和基于SSL的安全传输, ws端口是80,wss的端口为443.
WebSocket协议由两部分组成,握手和数据传输。
2-1 握手
WS的握手使用HTTP来实现的。客户端的握手消息是一个普通的,带有Upgrade头的,HTTP Request的消息。
先来看看如下代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>websocket</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body>
<script type="text/javascript">
var wsUrl = "wss://echo.websocket.org";
var ws = new WebSocket(wsUrl);
ws.onopen = function() {
console.log('open');
};
ws.onmessage = function(msg) {
console.log(msg.data);
}
ws.onclose = function() {
console.log('已经被关闭了');
}
</script>
</body>
</html>
页面运行后,我们可以看到链接到 wss://echo.websocket.org 期间记录的一个握手协议。先来看看客户端发送http的请求头:
GET /chat HTTP/1.1
Host:echo.websocket.org
Upgrade:websocket
Connection:Upgrade
Sec-WebSocket-Key:ALS2AoBJtUup67heKDgzFg==
Origin:file://
Sec-WebSocket-Version:13
服务器响应的头字段
Connection:Upgrade
Sec-WebSocket-Accept:qyzx/EgbRK15QNmr5PhpMQrPZMM=
Server: Kaazing Gateway
Upgrade:websocket
下面是请求和响应头字段的含义:
Upgrade: websocket, 告诉服务器这个HTTP链接是升级的WebSocket协议。
Connection:Upgrade 告知服务器当前请求链接是升级的。
Origin: 该字段是用来防止客户端浏览器使用脚本进行未授权的跨源攻击,服务器要根据这个字段是否接受客户端的socket链接。
可以返回一个HTTP错误状态码来拒绝连接。
Sec-WebSocket-Key: ALS2AoBJtUup67heKDgzFg==
Sec-WebSocket-Accept: qyzx/EgbRK15QNmr5PhpMQrPZMM=
Sec-WebSocket-Key 的值是一串长度为24的字符串是客户端随机生成的base64编码的字符串,它发送给服务器,服务器需要使用它经过一定的运算规则生成服务器的key,然后把服务器的key发到客户端去,客户端验证正确后,握手成功。
握手的具体原理:当我们客户端执行 new WebSocket(''wss://echo.websocket.org')的时候,客户端就会发起请求报文进行握手申请,报文中有一个key就是
Sec-WebSocket-Key,服务器获取到key,会将这个key与字符串258EAFA5-E914-47DA-95CA-C5AB0DC85B11相连,对新的字符串通过sha1安全散列算法计算出结果后,再进行Base64编码,并且将结果放在请求头的"Sec-WebSocket-Accept",最后返回给客户端,
客户端进行验证后,握手成功。握手成功后就可以开始数据传输了。
下面是实现一个简单的握手协议的demo,代码如下:
### 目录结构如下:
demo
|--- hands.html
|--- hands.js
hands.html 代码如下:
<html>
<head>
<title>WebSocket Demo</title>
</head>
<body>
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1:8000");
ws.onerror = function(e) {
console.log(e);
};
ws.onopen = function() {
console.log('握手成功');
}
</script>
</body>
</html>
hands.js 代码如下:
var crypto = require('crypto');
var WS = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
require('net').createServer(function(o) {
var key;
o.on('data', function(e) {
if (!key) {
console.log(e);
key = e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
console.log(key);
// WS的字符串 加上 key, 变成新的字符串后做一次sha1运算,最后转换成Base64
key = crypto.createHash('sha1').update(key+WS).digest('base64');
console.log(key);
// 输出字段数据,返回到客户端,
o.write('HTTP/1.1 101 Switching Protocol\r\n');
o.write('Upgrade: websocket\r\n');
o.write('Connection: Upgrade\r\n');
o.write('Sec-WebSocket-Accept:' +key+'\r\n');
// 输出空行,使HTTP头结束
o.write('\r\n');
} else {
// 数据处理
}
})
}).listen(8000);
首先在命令行中 进入相对应项目目录后,运行 node hands.js, 然后打开 hands.html 运行一下即可看到 命令行中打印出来如下信息:
$ node hands.js
<Buffer 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a 20 31 32 37 2e 30 2e 30 2e 31 3a 38 30 30 30 0d 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 ... >
+iHlfGTolBaWYpnyTIw22g==
W7IEsdQtwv8EP2204kssK/6pg+c=
然后在浏览器中查看请求头如下信息:
Request Headers:
Connection:Upgrade
Host:127.0.0.1:8000
Origin:file://
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:+iHlfGTolBaWYpnyTIw22g==
Sec-WebSocket-Version:13
Upgrade:websocket
响应头如下信息:
Response Headers:
Connection:Upgrade
Sec-WebSocket-Accept:W7IEsdQtwv8EP2204kssK/6pg+c=
Upgrade:websocket
如上信息可以看到,获取报文中的key代码:
key = e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
console.log(key); // 打印 +iHlfGTolBaWYpnyTIw22g==
和 Request Headers:中的 Sec-WebSocket-Key 值是一样的,该值是浏览器自动生成的,然后获取该值后,与 '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',相连,对新的字符串通过sha1安全散列算法计算出结果后,再进行Base64编码,
并且将结果放在请求头的"Sec-WebSocket-Accept",最后返回给客户端,客户端进行验证后,握手成功。在浏览器中可以看到打印出 握手成功了。
WebSocket原理与实践(二)---WebSocket协议的更多相关文章
- [从Paxos到ZooKeeper][分布式一致性原理与实践]<二>一致性协议[Paxos算法]
Overview 在<一>有介绍到,一个分布式系统的架构设计,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是产生了一系列的一致性协议. 为解决分布式一致性问题,在长期的探索过程中 ...
- WebSocket原理与实践(一)---基本原理
WebSocket原理与实践(一)---基本原理 一:为什么要使用WebSocket?1. 了解现有的HTTP的架构模式:Http是客户端/服务器模式中请求-响应所用的协议,在这种模式中,客户端(一般 ...
- WebSocket原理与实践(四)--生成数据帧
WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...
- WebSocket原理与实践(三)--解析数据帧
WebSocket原理与实践(三)--解析数据帧 1-1 理解数据帧的含义: 在WebSocket协议中,数据是通过帧序列来传输的.为了数据安全原因,客户端必须掩码(mask)它发送到服务器的所有 ...
- WebSocket原理与实践
开题思考:如何实现客户端及时获取服务端数据? Polling 指客户端每隔一段时间(周期性)请求服务端获取数据,可能有更新数据返回,也可能什么都没有,它并不在乎服务端数据有无更新.(Web端一般采用a ...
- RPC原理与实践(二)----Thrift分层模型
这一节我们从一下几个方面来讲一下Thrift的分层架构,按照官方的定义这是Thrift的网络栈,其中网络栈中分为一下几个部分,(由栈顶到栈底)server,processor,protocol,tra ...
- HTML5(十二)——一文读懂 WebSocket 原理
一.WebSocket 由来 WebSocket 是一个持久化的协议,通过第一次 HTTP Request 建立连接之后,再把通信协议升级成 websocket,保持连接状态,后续的数据交换不需要再重 ...
- 萌萌的websocket原理解析
转载自:http://www.zhihu.com/question/20215561 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持 ...
- WebSocket原理及与http1.0/1.1 long poll和 ajax轮询的区别【转自知乎】
一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算)首先HTTP有1.1和1.0之说,也就是所谓的ke ...
随机推荐
- C-指针,二级指针,二维数组作为函数参数使用,C语言链表(详解)
一级指针 int *p; //表示定义一个int型(4字节)的指针p &p //表示p自身的地址位置 p ...
- GIS基础知识
投影转换 若两者地理坐标系不一致,需要设置七参数进行转换. 不同地方,七参数大小不一样,需要通过计算得到.
- NopCommerce 根据手机浏览器和桌面浏览器切换 Theme
自从 NopCommerce 升级到 3.x 以来,默认的 ViewName.Mobile.cshtml 方式就被响应式的默认 Theme 取代了. 但是在今天各种手机专用前端库大行其道的情况下,响应 ...
- WebAPI路由、参数绑定
一.测试Web API a)测试Web API可以用来检测请求和返回数据是否正常,可以使用Fiddler.Postman等工具.以Fiddler为例,这是一个http协议调试代理工具,它能够记录客 ...
- 喜闻乐见-Activity生命周期
Activity的生命周期,对于Android开发者来说,再熟悉不过了.但是我们接触到的资料,绝大部分都只是谈了一些表面上的东西,例如各个回调的顺序等等.本文试图换个角度来讲解,也希望对各位读者有所帮 ...
- SpringMVC处理请求
HttpServletBean HttpServletBean主要参与了创建工作,并没有涉及请求的处理. FrameworkServlet FrameworkServlet的service方法里添加了 ...
- Storm的DRPC
RPC:Remote Procedure Call DRPC:Distributed RPC Hadoop提供了RPC的实现机制,实现方法见:<>,本文主要介绍Storm的DRPC. ...
- (网页)java中Collections.sort排序详解(转)
转自CSDN: Comparator是个接口,可重写compare()及equals()这两个方法,用于比价功能:如果是null的话,就是使用元素的默认顺序,如a,b,c,d,e,f,g,就是a,b, ...
- scrapy系列(四)——CrawlSpider解析
CrawlSpider也继承自Spider,所以具备它的所有特性,这些特性上章已经讲过了,就再在赘述了,这章就讲点它本身所独有的. 参与过网站后台开发的应该会知道,网站的url都是有一定规则的.像dj ...
- HttpClient与浏览器调用服务接口差异
我用httpclient访问接口,统计图有些不均匀,差距较大 ,有时只有几十毫秒,下图看到这种情况占多数,600-800毫秒之间的算是浏览器正常的产生调用接口的时间耗时 然后用jmeter跑时都是均值 ...