[聚合文章] 小姐姐,来看看 Websocket 啊

HTML5 2017-12-30 15 阅读

2017的北京的冬天,显得格外的冷,又干又冷,新闻里说,这样的天气有利于北京的空气质量的提升,霾没了,截止到29号看来,并没有,而且雪也没了,等了一冬天,毛都没有见到。一个人等雪的时候,稍微略显寂寞,不如来看看websocket吧~

阿伟

阿伟第一次接触互联网的的时候是 2001年,十几岁的他,就好像同样豆蔻年华的互联网一样,还是略显稚嫩,不知道怎么样跟心爱的女孩子交流,也不知道怎样才能叩开花季少女的心扉。阿伟一直在想,一直在冥思苦想,人与人之间应该怎样交流,人与人之间怎么样才能建立联系,人与人之间又怎么样才能坠入爱河,直到他学了计算机网络,他才恍然大悟。

而让他悟出这一切的正是OSI七层数据模型,如下图

点击图片查看大图

在网络中的两个点如果需要进行通信,他们需要经过一层层协议的封装,我们常见的就像是TCP协议,IP协议,他们在网络模型中都有对应的层级,而我们最常用的HTTP协议就是最顶端应用层的协议。

阿伟懂了,两个人如果在茫茫人海中相遇,必须通过一定的协议来进行交流和沟通,否则一切都是空谈,我听不懂你,你不了解我。

阿伟有了心爱的姑娘,他想和她在一起一辈子。

说好的一辈子,差一分,差一秒,都不算。

可是那个年代,怎么样才能跟心爱的姑娘实时在一起啊,大多数人还是选择了写信。可是写信啊,你写一封,对方回一封,这个过程没有任何错误。就好像HTTP协议一样,我发送一个请求,就必然要收到一个请求,不然浑身难受。

可是,年轻的阿伟,热血的阿伟等不及啊。这时候他就有了一个大胆的想法,他从ajax轮询中得到了启发,客户端隔个几秒就发送一次请求,向服务器询问数据是否更新。于是他每天都给心爱的小姐姐写信,询问是否有新鲜的事情,善良的小姐姐也会给他回信,只是并不是每次回信都有新内容。

但是他觉得这样不好,太浪费纸了。

后来他又从long poll中找到了灵感,所谓long poll,即客户端和服务端通过请求建立了连接之后,连接一直保持,服务端直到有消息了才把请求返回给客户端。阿伟之所以能这样做,因为他要到了姑娘的电话,他打电话,两人羞涩,竟不知说些什么好,谁也不肯挂掉电话,但是两人的心头都是暖暖的。

后来,电话费太贵了,阿伟还是受不了。

可是这有何妨,阿伟的努力还是得到了回报,二人终于在一起了。

阿伟终于明白了,原来他们说的是真的,从前车马很慢,书信很远,一生只够爱一个人。

在那个年代,HTTP协议,还是浏览器和服务器交互的标准,一个又一个的请求从发出到返回,不知道多少思念和祝福在网上流转着,但是始终实时交流考验着每个人的心儿,无论ajax轮询还是long poll,都有着不可规避的缺点,前者创造了太多的无用请求,后者则对服务器造成了巨大的负荷,时代渴望着一个可以支持实时的协议。上帝说,要有光,于是,就有了光。而这道光就是Websocket。

阿辉

阿辉喜欢《王者荣耀》的张飞,叱咤风云,神挡杀神,佛挡杀佛,当然需要变身。室友问如果你女朋友住院了,你朋友找你王者开黑,你选哪一个,阿辉说,我选张飞吧,我张飞贼溜。老段子了,上次讲这个段子的时候,阿辉还是有女朋友小洁的。

小洁是个学霸,最喜欢跟阿辉讲Websocket。

辉仔,你知道什么是Websocet么?

打团了,打团了,程咬金,不要瞎跑!并没有理她。

哼,小洁冷哼一声

知道知道,不就是HTML5集成的那套规范么?太简单了,待会我给你写一遍~先让我打一波团。阿辉不耐烦道。

你说的这个,没想到小洁拿出了一张纸,上面写着几行代码

if ("WebSocket" in window) {
   alert("您的浏览器支持 WebSocket!");   
   // 打开一个 WebSocket
   var ws = new WebSocket("ws://localhost:9000");
   ws.onopen = function(){      
      // WebSocket 已连接上,使用 send() 方法发送数据
      ws.send("发送数据");
      alert("数据发送中...");
   };
   ws.onmessage = function (evt){
      // 监测信息
      var received_msg = evt.data;
      alert("数据已接收...");
   };
   ws.onclose = function(){      
      // 关闭 WebSocket
      alert("连接已关闭...");
   };
}else{   // 浏览器不支持 WebSocket
   alert("您的浏览器不支持 WebSocket!");
}

对对,不就是这个么,这个不就是Websocket么!兄弟,等我再开团~。

小洁小嘴一撅,瞬间不大开心了。跟你说了多少次了,WebSocket指的是Websocket协议,WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端,而HTML5集成的是Websocket API。算了,我觉得我们不合适,我们分手吧。

打啊,推塔啊。啊?你说啥?

我说我们不合适,分手吧。小洁转身离去,留下了阿辉错愕而震惊的表情,但是阿辉还是忍受着失恋的痛苦坚持打完了游戏,赢了,但是阿辉突然觉得没意思了,赢得了游戏,失去了你,又有什么意义。可惜阿辉醒悟的太晚。

小洁走后,阿辉开始真正理解Websokcet的真正含义,他常常在心中模拟Websocket连接建立的过程。

阿辉开启了一个Websocket服务器,然后打开了Chrome,在浏览器立认认真真的开启了一个连接,然后打开network面板,他看到了一个请求,他想起了小洁,善良可爱的小洁。 就像小洁讲的那样,第一个请求是HTTP协议,但是附带了升级协议的Header

眼泪噙满了阿辉的眼睛,阿辉紧握着手,鼠标一点点打开了折叠的Response Headers, 协议被升级了,阿辉终于控制不住自己,留下了悔恨的泪水,他想小洁了,灰常想。

阿辉想小洁的时候,就去默默去看Websocket的协议,这个协议是独一无二的,就好像小洁是独一无二的。 阿辉甚至把下面Websocket的协议帧格式做成了自己的被套,每天盖在身上,他觉得,这样,小洁还在他身边,还在陪着他。

阿辉还在打游戏,只是打游戏的时候还会想起小洁。又是一个夜晚,阿辉梦见自己变成了张飞,一开始就像第一个发出的HTTP请求一样,羞涩,突然cd时间一到,就像服务器收到了请求一样,协议升级成了Websocket协议,自己也壮实起来了,很好,很强大,只是,没了小洁。

阿江

阿江是个90后,可是开始秃了。阿江虽然开始秃了,可是阿江有女朋友。阿江虽然有女朋友,但是阿江是有了女朋友之后,才开始秃的。阿江很担心,阿江很惆怅。

不知道为何,阿江发现女朋友最近开始研究使用node写一个Websocket服务器了,这样阿江的头皮发麻了一下,阿江不知所措,难道女友要离开自己了么。

有一天,女友把阿江叫了过来,一起review代码

const http = require('http');
const crypto = require("crypto");
const server = http.createServer((req, res) => {
   res.end();
});

server.on('upgrade', (req, socket, head) => {
  // 获取请求头的信息,并处理
  let key = req.headers['sec-websocket-key'];
  key = crypto.createHash("sha1").update(key +  "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
  // 返回对应的Headers信息
  const headers = [
    'HTTP/1.1 101 Switching Protocols',
    'Upgrade: websocket',
    'Connection: Upgrade',
    'Sec-WebSocket-Accept: ' + key
  ];
  socket.setNoDelay(true);
  socket.write(headers.join("\r\n") + "\r\n\r\n", 'ascii');
});

server.on('clientError', (err, socket) => {
  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

server.listen(9000);

女友说,你看,我照着网上的教程写了个Websokcet的服务器耶,但是我还有好多不懂的地方,你给我讲讲~

阿江细心跟女友讲解着,这个demo只是成了当服务器接收到请求之后,如果监听到upgrade,就会取请求头里面的sec-websocket-key,经过处理,并且返回对应的Headers,告知客户端已经升级成Websocket协议了。只是这还是个简单的demo,还没有添加将信息处理成Websocket协议帧的方法,还有好多要做的地方要完善,阿江不懂女友为什么要学这个,学好了这个,女友就会离开自己了么,我就知道当初就是看中我的技术好,现在我开始秃了,技术的Buff不再了,一定是因为这样,阿江还是忍不住问了,你是不是要离开我了。

傻瓜,为什么这样说。

你为什么要学这个。

你是不是之前学过这个?

我啊,最近看你愁眉不展,就像走走你走过的路,听你听过的歌,尝试你曾经做过的一切,但这并不是想证明我有多爱你,我只是想离你更近一点。你那么可爱,我怎么舍得离开呢。而且看你最近不开心,想知道你为什么而已。

阿江的眼里噙满了泪水,将女朋友拥入怀中~

阿欢

阿欢最近开始研究Websocket,他查遍资料,很多论坛都推荐了socketio,为什么呢,阿欢不禁问道。

阿欢把官方的demo clone下来仔细研究起来。

以聊天室为例,浏览器客户端的代码

html
// 页面上引用socketio.js
<script src="/socket.io/socket.io.js"></script>

js代码

// 创建一个链接
var socket = io();

// 监听login事件
socket.on('login', function (data) {  
  // Todo
});
// 触发add user事件,服务端会接收到
socket.emit('add user', username);

node服务端的代码

//不是完整代码

const server = require('http').createServer(app);
const io = require('../lib')(server);

let numUsers = 0;

io.on('connection', function (socket) {   
   var addedUser = false;   
   // 监听到客户端发送的new message信息,并做处理
   socket.on('new message', function (data) {
   // 向所有的客户端广播new message
     socket.broadcast.emit('new message', {
       username: socket.username,
       message: data
     });
   });
   // 当监测到添加用户的时候的处理
   socket.on('add user', function (username) {
     if (addedUser) return;
     // 保存用户名
     socket.username = username;
     ++numUsers;
     addedUser = true;
     // 像对应客户端触发login事件
     socket.emit('login', {
       numUsers: numUsers
     });
     
     // 向所有客户端广播user joined事件
     socket.broadcast.emit('user joined',{
       username: socket.username,
       numUsers: numUsers
     });
   });
});

阿欢疑惑,代码太简单了, 客户端 代码甚至没有看到使用Websocket啊,突然阿欢有个大胆的想法,机智的阿欢打开了调试界面,惊奇的发现,竟然发出了三个请求,原来socketio竟然做了兼容,不紧有Websocket,同时考虑到不支持Websocket的环境,它尽然主动polyfill了,当然兼容主要用的还是轮询的方式。

再看服务端的代码也不难发现,没有涉及到协议的升级,这就说明socketio做了程度很大的包装,让使用者更注重业务的开发。

阿欢心头一暖,内心激动无比,不禁感谢这个时代,这个美妙而和谐的时代。这么多人努力着,奋斗者,为了把这个世界弄得更美好。

阿寻

阿寻很是忧伤,忧伤的不知所以,回想这一年,前端的技术发展让他有些不知所措,日新月异的速度让他觉得这个世界都有点假假的感觉了,但是看了看比特币的价格变化,阿寻又觉得前端的变化速度也不是很快。

Alice发给了阿寻的一篇文章 Will WebSocket survive HTTP/2?

https://www.infoq.com/articles/websocket-and-http2-coexist/

阿寻想,为什么要发给我这种文章,知道我最近正在学习Websocket么?阿寻大致看了下文章,在比较了Websocket和HTTP2,之后,作者给出了自己的观点,Websocket会存活下来,只是阿寻又陷入了惆怅,说不定哪天会被其他技术干掉呢。

阿寻心头一紧,觉得Alice是在嘲笑自己,嘲笑自己没有能洞悉时代的趋势,没能紧跟技术的浪潮啊,阿寻更加沮丧了。

阿寻对Alice说,完了,我跟不上这个时代了。

Alice很诧异,说咋啦。

阿寻说,我看你发我的文章,Websocket我还没吃透,感觉随着技术的发现,早晚又会被淘汰了呢。

Alice说,啊,我就是让你看看,你英文这么差,练练英文啊,哪有想这么多。再说,根据文章的描述以及国内的环境, Websocket还是目前最被认可的技术, 那么现在来说Websocket还是大有用途的。

阿寻说,我最近觉得我就像被上帝抛弃了一样,感觉要被淘汰,我觉得我快失业了。

Alice说,至于么,或许某天,Websocket会被新技术取代,但是至少肯定不是今天。如果那天真到了,你也不一定失业啊。如果你真的失业了,我养你啊~

阿寻有些懵逼,你再说一遍。

Alice说我说,我养你啊~

阿寻身体忍不住颤抖起来,你再说一遍。

Alice:我说你失业了,我养你啊~

阿寻说想了一会儿,说好,我也养你~

是啊,只要Alice还在,阿寻就充满了斗志。技术的更迭不再困惑阿寻了,兵来将挡水来土掩,再学就是了。

结语

这一年,阿猿们依旧努力奋斗着,与天斗,与地斗,与八阿哥斗,昼伏夜出,披星戴月,吸天地之灵气,取日月之精华,有些人倒下了,有些人离开了,但是还有些人任然坚持着,他们感激着过去奋斗着2017的每一天,展望着即将到来的2018的每一天。

两句歌词送给大家~

一往无前虎山行,拨开云雾见光明。

梦里花开牡丹亭,幻想成真歌舞升平。 

——GAI

祝大家新年快乐

买彩票中大奖

据说留言许愿,来年实现的概率就会翻倍哦~

参考文献

  1. Web 通信 之 长连接、长轮询(long polling)

    https://www.cnblogs.com/hoojo/p/longPolling_comet_jquery_iframe_ajax.html

  2. webSocket、Ajax轮询、长轮询(long poll)

    http://blog.csdn.net/lb7758zx/article/details/51513353

  3. nodejs socket 服务端和客户端

    http://blog.csdn.net/lxhjh/article/details/40686481

  4. 学习 NodeJS 第八天:Socket 通讯

    http://blog.csdn.net/zhangxin09/article/details/12844975

  5. nodejs实现Websocket的数据接收发送

    https://www.cnblogs.com/axes/p/4514199.html

  6. HCNA-HNTD——以太网帧结构

    http://blog.csdn.net/wdkirchhoff/article/details/43915825

  7. OSI七层模型详解

    http://blog.csdn.net/yaopeng_2005/article/details/7064869

  8. OSI七层模型与TCP/IP五层模型

    https://www.cnblogs.com/qishui/p/5428938.html

  9. TCP/IP、Http、Socket的区别

    http://jingyan.baidu.com/article/08b6a591e07ecc14a80922f1.html

  10. WebSocket数据包协议详解

    https://www.cnblogs.com/smark/archive/2012/11/26/2789812.html

  11. The WebSocket Protocol

    https://datatracker.ietf.org/doc/rfc6455/?include_text=1

  12. Will WebSocket survive HTTP/2?

    https://www.infoq.com/articles/websocket-and-http2-coexist/

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。