WebSocket

在H5,js代码新增了WebSocket的API。这玩意儿,从使用上来说,不难,也就onopen、onclose、onmessage、onerror这几个接口而已,前段时间使用的时候,就还是不由自主地去看一些这方面的东西。

Websocket是基于TCP协议上实现的,也有借助HTTP协议,但与HTTP1.X协议不同地方是,WebSocket是长连接,双方只需要一个握手动作(这里是借助HTTP协议),就可以建立一条连接通道,接着就能相互传输数据了;而HTTP1.X是短连接的,每次发起请求都要在TCP层来个3次握手,数据传输完或到指定的超时时间后就断开连接,若要多次请求,就要不断发起请求,这样挺占带宽。
Websocket在服务器方面,只需增加支持即可,如Python的tornado框架就支持,golang也挺多的,但我用的是大猩猩:gorilla。web服务器上,nginx在1.3.13版本也支持;其他web server,自行去搜索吧。浏览器方面除了老IE系,其他浏览器目前的新版本基本都支持WebSocket。

Javascript的接口

var conn = new WebSocket("ws://ip:port/");
conn.onclose = function(evt) {
    console.log(evt);
}

conn.onmessage = function(evt) {
    console.log(evt);
}

conn.onopen = function(evt) {
    console.log(evt);
}

conn.onerror = function(evt) {
    console.log(evt);
}

各接口看名称就知道是什么意思了。
浏览器与服务端建立连接的时候,要经过一个Websocket握手协议

GET /ws HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 172.16.1.11
Origin: http://example.com
Sec-WebSocket-Key: BVuKSx8KJKN2VAGM0i6gjw==
Sec-WebSocket-Version: 13

这是正常的HTTP的GET请求,然后在请求头里增加了

Upgrade: websocket
Connection: Upgrade

这等于告诉web服务器,发起的请求是Websocket协议的,要用Websocket协议方式来处理请求。

在请求头里,还增加了

Sec-WebSocket-Key: BVuKSx8KJKN2VAGM0i6gjw==

看值的话,就应该能猜到,是通过BASE64编码而成的值,这是浏览器随机生成的。

HTTP响应头
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: sr0Tsn4bYggO1mzRZHpiOQO+FYE=

Sec-WebSocket-Accept这个是通过服务器确认,并加密后的Sec-WebSocket-Key。下面的这个响应头代表告诉客户端,升级成Websocket协议,属于HTTP最后负责地方

Upgrade: websocket
Connection: Upgrade

为什么说是HTTP最后负责的地方?因为WebSocket只是借助了HTTP协议去握手,仅此而已。此后信息通讯时,并不基于HTTP协议,而是基于更底层的TCP协议。WebSocket是一个和HTTP协议一样是基于TCP协议上的应用层协议。

数据收发

Websocket是可以发数据类型消息,也可以发控制类型消息。
数据类型消息包含:纯文本消息,二进制消息
控制类型消息包含:Ping,Pong,Close

更准确的说,WebSocket消息传输包含数据帧和控制帧,控制帧包含Ping,Pong,Close

这3个帧的Opcode各不相同:
  1. Ping帧的Opcode是9,0x09
  2. Pong帧的Opcode是10,0x0A
  3. Close帧的Opcode是8,0x08
数据帧包含文本帧和二进制帧
  1. 文本帧的Opcode是1,0x01
  2. 二进制帧的Opcode是2,0x02

还有一个既非数据帧,也非控制帧,是0x00,代表继续帧。
通过上面几个数字看到,还缺了几个数字,这几个缺了的数字是协议保留,以备后用。

保留帧
  1. 0x03——0x07:保留用于未来的非控制帧
  2. 0x0B——0x0F:保留用于未来的控制帧

还有其他的具体解释在:传送门

ping帧的数据传输
ping

可以看到opcode是数字9

pong帧的数据传输
pong

可以看到opcode是数字10

close帧

下图是服务器主动断开连接,opcode为10,在红框处,有一个十六进制的数字,还有一串英文解释。
第一个Close表示的是关闭的代码,第二个Close表示的是关闭的原因。
关闭的reason也可以自定义,但reason内容的长度别过长(之前试过大概在128个字节左右,具体的可以再试试),否则数据传输不了导致无法断开的问题。
websocket的状态码具体详解在这:传送门

92701058-92E0-4E07-AFDA-2F394CD66CF1.png

在js的接口中,没有主动发起ping接口的调用,这一般是在服务器那发起ping请求,浏览器接收到ping帧后,就会回个pong帧,从而达到心跳效果。

发送文本数据

从web界面向服务器发送32个‘f’,截取传输数据如下图:


C4B0F5CA-49D3-4F27-8193-ABA7A52DB91D.png

Payload length代表数据长度。以字节的形式表示:7位、7+16位、或者7+64位。如果这个值以字节表示是0-125这个范围,那这个值就表示传输数据的长度;如果这个值是126,则随后的两个字节表示的是一个16进制无符号数,用来表示传输数据的长度;如果这个值是127,则随后的是8个字节表示的一个64位无符号数,这个数用来表示传输数据的长度。多字节长度的数量是以网络字节的顺序表示。负载数据的长度为扩展数据及应用数据之和,扩展数据的长度可能为0,因而此时负载数据的长度就为应用数据的长度。Payload length不包括Masking-key在内。
Masking-key,呃,掩码键。
还有好多其他说明,都去传送门里看吧。。

其他

之前在网上无意间看到这图,觉得挺不错的,描述建立连接时,websocket和TCP层的握手关系,很一目了然


handshake

在建立建立之后,每次端对端之间发送数据,另一端在TCP层都会回发个ACK表示确认。
WebSocket只是个协议,不是只能运行在浏览器上,自行用手机/其他客户端也可以实现,只需遵循协议即可(目前协议文档是RFC6455),个人觉得,假如没有其他更好想法,用这个协议来代替很多TCP层的数据传输格式也是不错的。

还有一个是IBM公司搞的MQTT协议,之前了解过其主要用于嵌入式设备,说是比较省电(相对于HTTP协议来比较那的确是),使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。它跟Websocket一样也是基于TCP协议的,都有各自的协议头格式。

呃,网上搜的时候,很多人都有对这些方面研究了,解释的更好
张善友

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • 前言 本文为初入研究 Websocket协议,对于真正应用中,各种语言都有实现库,建议采用库,而不是自己实现,本文...
    MeIsLZHua阅读 8,582评论 6 39
  • 上篇介绍了HTTP1.1协议的基本内容,这篇文章将继续分析WebSocket协议,然后对这两个进行简单的比较。 W...
    TheAlchemist阅读 36,522评论 15 113
  • 琪宝 暖风吹过我的窗台 抬眸,隐约的绿影浮现 原来,一树春意早已悄然袭来 我的热情捱过寒冬的掩埋 冰雪的覆盖 褪去...
    琪宝angel阅读 269评论 1 1
  • 人大概都曾有这样的感觉,遇到一个人有似曾相识的感觉,我胡乱猜想,也许是在街角的某次擦肩而过,我们四目相对,心中虽没...
    樯脚摘蘑菇阅读 489评论 0 0
  • http://www.exp99.com/htmlcss/htmlcss_229.htmlhttp://www.f...
    孙雪冬阅读 187评论 0 0