一、前言

  之前做了一个Web小项目,需要实现后端持续给前端推送消息的功能,当时最开始使用的是轮询实现,但是效率太低,对资源消耗也大。之后为了解决这个问题,上网查阅资料后,改用了WebSocket实现,前后端直接建立全双工的连接传递消息。但是当时只是学习了一下怎么使用,没有具体研究WebSocket是什么,以及实现原理。这段时间花了点时间重新了解了一下,这篇博客就来简单介绍一下。

二、正文

  2.1 什么是WebSocket

  WebSocketHTTP一样,是一个应用层的网络协议,它的作用是可以使客户端和服务器在应用层建立一个全双工的连接,然后通过这个连接,客户端和服务器就可以互相传递数据。有的人可能会问,HTTP不是也能实现客户端和服务器传递数据,为什么还需要WebSocket呢?下面我就来对WebSocket以及HTTP做一个对比。

  2.2 WebSocket、HTTP的区别与联系

  首先来说HTTP。我们知道,HTTP是一个无状态的协议,也就是说,在服务器端并不会记录发送请求的客户端的身份,这也就意味着HTTP服务器不会主动向客户端发送消息。事实也确实如此,HTTP协议实现的是请求-响应模型,只有当客户端向服务器发送请求,服务器才会向客户端回送数据。熟悉HTTP协议的应该知道,HTTP连接分持续连接非持续连接,对于使用非持续连接的HTTP客户端,每一次连接只会有一次请求;而对于持续连接,则一个连接可以有多个请求,但是这个连接也是有时效的,几十秒或者几秒后这个连接就会被释放。服务器不会主动发送消息,意味着如果我们需要实现一个类似消息推送的功能(比如聊天室),则需要客户端每隔一段时间向服务器发出一次请求,询问是否有自己的消息,这就是轮询。而由于HTTP连接维持时间较短,意味着可能客户端的每一次询问,都要重新建立一个HTTP连接,这不仅效率低下,而且十分消耗资源。正因为如此,才需要WebSocket

  WebSocket正是为了解决这样的问题而被发明出来。WebSocket是一个应用层的协议,它依靠HTTP实现连接前的握手,而底层依赖TCP协议传递消息。在建立连接阶段,客户端依靠HTTP连接,与服务器进行一次握手,当握手完成后,WebSocket连接便建立完成,这之后客户端就可以与服务器进行通信了。需要强调的是,WebSocket依赖TCP进行数据传输,这也就意味着这是一个全双工的连接,即服务器可以主动向客户端发送消息,而不需要客户端的请求;客户端也可以自由的向服务器发送消息。更重要的是,TCP是一个持久的连接,而基于它的WebSocket自然也是一样的,只要两端没有发起断开连接的请求,且连接没有长时间闲置,则在不发送异常的情况下,这个连接将一直存在。这就很好地解决了轮询重复建立连接的弊端。

  2.3 WebSocket建立连接的过程

  下面我们具体来说一说WebSocket如何建立连接。前面说过,WebSocket基于HTTP进行握手从而建立连接,使用HTTP协议是为了兼容服务于HTTPWeb服务器以及中间代理服务器。下面我就来详细说一说握手的三个阶段。

(1)客户端向服务器发送HTTP请求报文

  握手的第一个阶段:客户端与服务器建立HTTP连接,并发送请求报文,请求报文的格式如下:

GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com
Origin: HTTP://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

  可以看到,这个请求是一个GET请求,请求中必须包含这些首部信息:

  • Host:需要建立连接的服务器名称;
  • Connection:必须包含此首部,且值必须为Upgrade,表明这是一个协议升级请求;
  • Upgrade:必须包含此首部,且值必须为WebSocket,表明当前连接请求升级为WebSocket连接;
  • Origin:如果这个请求是从浏览器发出的,那么还必须带有Origin请求头;
  • Sec-WebSocket-Key:这是浏览器随机生成的值,用来验证服务器身份;
  • Sec-WebSocket-Version:这个表示的是WebSocket的版本号码;

(2)服务器接收请求,并响应

  握手第二个阶段:服务器接收到了客户端发来的协议升级请求,会先判断请求报文是否合法,若没有什么异常,则会给客户端发送响应,响应报文如下:

HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=

  需要注意一点,响应报文的状态码是101101状态码的含义是:服务器正在根据客户端的指定,将协议切换为请求报文中Upgrade指定的协议。下面我们来说一说响应报文中的首部:

  • Connection:值和请求报文中一致,表明这是一个协议升级请求的响应报文;
  • Upgrade:值为WebSocket,表明这个响应报文,响应的协议升级请求,是希望升级为WebSocket协议;
  • Sec-WebSocket-Accept:这个值是服务器接收到客户端发来的Sec-WebSocket-Key值后,经过加密计算出来的值,用来向客户端表明自己的身份;

(3)客户端验证服务器身份

  客户端接收到服务器发回来的响应报文后,将对响应报文进行校验:

  • 首先客户端将检测响应的状态码是否为101,若不是,表明协议升级失败,连接自然无法建立;
  • 若状态码正常,则接着检测Sec-WebSocket-Accept的值。客户端使用相同的加密方式,对Sec-WebSocket-Key进行计算,若计算的结果与服务器发来的Sec-WebSocket-Accept的值一致,表明服务器身份没有问题,于是连接成功建立,否则放弃建立连接;

  连接建立后,客户端和服务器就可以基于TCP,进行全双工的通信了。

三、总结

  上面的内容对WebSocket的机制做了一个大致的介绍,相信对于看完之后会对WebSocket的工作机制有一个大致的了解。以上内容描述的比较简单,若有补充或者发现错误,欢迎指正。关于WebSocket的详细介绍,可以参考规范文档【RFC6455】:HTTPs://tools.ietf.org/html/rfc6455#page-41。

四、参考

计算机网络——简单说说WebSocket协议的更多相关文章

  1. Websocket 协议解析

    WebSocket protocol 是HTML5一种新的协议.它是实现了浏览器与服务器全双工通信(full-duplex).          现 很多网站为了实现即时通讯,所用的技术都是轮询(po ...

  2. WebSocket协议开发

    一直以来,网络在很大程度上都是围绕着HTTP的请求/响应模式而构建的.客户端加载一个网页,然后直到用户点击下一页之前,什么都不会发生.在2005年左右,Ajax开始让网络变得更加动态了.但所有的HTT ...

  3. 初识WebSocket协议

    1.什么是WebSocket协议 RFC6455文档的表述如下: The WebSocket Protocol enables two-way communication between a clie ...

  4. Websocket协议的学习、调研和实现

    本文章同时发在 cpper.info. 1. websocket是什么 Websocket是html5提出的一个协议规范,参考rfc6455. websocket约定了一个通信的规范,通过一个握手的机 ...

  5. SMTP 简单邮件传输协议

    SMTP 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传 ...

  6. WebSocket协议

    websocket 简介 (2013-04-09 15:39:28) 转载▼   分类: websocket 一 WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例 ...

  7. 开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析

    很久没有写博客了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的.(整天催我代码的人,还望多多谅解啊,我会坚持写我们的项目的,还是需要相信我的,毕竟这是一个 ...

  8. WebSocket协议:5分钟从入门到精通

    一.内容概览 WebSocket的出现,使得浏览器具备了实时双向通信的能力.本文由浅入深,介绍了WebSocket如何建立连接.交换数据的细节,以及数据帧的格式.此外,还简要介绍了针对WebSocke ...

  9. 刨根问底HTTP和WebSocket协议

    HTML5的新成员:WebSocket 上篇介绍了HTTP1.1协议的基本内容,这篇文章将继续分析WebSocket协议,然后对这两个进行简单的比较. WebSocket WebSocket协议还很年 ...

随机推荐

  1. 疲劳驾驶打瞌睡?python保障您的驾驶安全

    道路千万条,安全第一条!疲劳驾驶可谓交通事故几大罪魁祸首之一,根据美国一项研究显示,司机睡眠不足4小时,交通事故肇事几率等同于醉驾. 为了减少疲劳驾驶现象,驾驶员疲劳检测应运而生.这是一项安全技术,可 ...

  2. vue2.x学习笔记(十三)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12595860.html. 组件的注册 注册组件有一些规范约定与注意事项. 组件名的命名规范 在注册一个组件的时候, ...

  3. APP测试和WEB测试区别

    App测试web测试的区别 单纯从功能测试的层面上来讲的话,APP 测试.web 测试 在流程和功能测试上是没有区别的 根据两者载体不一样,则区别如下: 1.兼容性测试:web端兼容浏览器,app端兼 ...

  4. [Laravel框架学习二]:Laravel的CURD和查询构造器的CURD,以及聚合函数

    public function index() { //return Member::getMember();//这是调用模型的方法 return view('lpc',[ 'age'=>18, ...

  5. vim环境下空格和tab键互换

    对于已保存的文件,可以使用下面的方法进行空格和TAB的替换 TAB替换为空格::set ts=4:set expandtab:%retab! 空格替换为TAB::set ts=4:set noexpa ...

  6. Redis 的 maxmemory 和 dbnum 默认值都是多少?对于最大值会有限制吗?

    一.Redis 的默认配置 了解 Redis 的都知道,Redis 服务器状态有很多可配置的默认值. 例如:数据库数量,最大可用内存,AOF 持久化相关配置和 RDB 持久化相关配置等等.我相信,关于 ...

  7. Python pandas库159个常用方法使用说明

    Pandas库专为数据分析而设计,它是使Python成为强大而高效的数据分析环境的重要因素. 一.Pandas数据结构 1.import pandas as pd import numpy as np ...

  8. <vector>常用操作

    如果不清楚vector是什么的话就去看我的另一篇随笔吧:https://www.cnblogs.com/buanxu/p/12791785.html 进入正题,vector和string一样,也是一种 ...

  9. 在c++中引用c头文件里的函数

    在c++中有的时候想要引用c头文件里的函数有两种方法;就拿c语言里面的<stdlib.h>举例 在c中我们想要用<stdlib.h>里的函数,形式为:#include<s ...

  10. ThinkPHP框架初步掌握

    为了帮老师用ThinkSNS二次开发一个微博系统,专门花了几天学习ThinkPHP框架,现在将一些ThinkPHP入门知识作以记录. 首先声明: 本文不是完全教程,只是将开发中碰到的问题作以总结,如果 ...