Websocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信的问题而设计的,是完全意义上的Web应用端的双向通信技术,可以取代之前使用半双工HTTP协议而模拟全双工通信,同时克服了带宽和访问速度等的诸多问题。协议定义为ws和wss协议,分别为普通请求和基于SSL的安全传输,占用端口与http协议系统,ws为80端口,wss为443端口,这样可以支持HTTP代理。

协议包含两个部分,第一个是“握手”,第二个是数据传输。

一、Websocket URI

定义的两个协议框架ws和wss与http类似,而且各自部分的要求也是在HTTP协议中使用的一样,各自的URI如下:

ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
        wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]

其中port是可选项,query前接“?”。

二、握手(Opening & Closing Handshake)打开连接

当建立一个Websocket连接时,为了保持基于HTTP协议的服务器软件和中间件进行兼容工作,客户端打开一个连接时使用与HTTP连接的同一个端口到服务器进行连接,这样被设计为一个升级的HTTP请求。

1、发送握手请求

此时的连接状态是CONNECTING,客户端需要提供host、port、resource-name和一个是否是安全连接的标记,也就是一个WebSocket URI。

客户端发送的一个到服务器端握手请求如下:

        GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

这个升级的HTTP请求头中的字段顺序是可以随便的。与普通HTTP请求相比多了一些字段。

  • Sec-WebSocket-Protocol:字段表示客户端可以接受的子协议类型,也就是在Websocket协议上的应用层协议类型。上面可以看到客户端支持chat和superchat两个应用层协议,当服务器接受到这个字段后要从中选出一个协议返回给客户端。
  • Upgrade:告诉服务器这个HTTP连接是升级的Websocket连接。
  • Connection:告知服务器当前请求连接是升级的。
  • Origin:该字段是用来防止客户端浏览器使用脚本进行未授权的跨源攻击,这个字段在WebSocket协议中非常重要。服务器要根据这个字段判断是否接受客户端的Socket连接。可以返回一个HTTP错误状态码来拒绝连接。
  • Sec-WebSocket-Key:为了表示服务器同意和客户端进行Socket连接,服务器端需要使用客户端发送的这个Key进行校验,然后返回一个校验过的字符串给客户端,客户端验证通过后才能正式建立Socket连接。服务器验证方法是:首先进行 Key + 全局唯一标示符(GUID)“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”连接起来,然后将连接起来的字符串使用SHA-1哈希加密,再进行base64加密,将得到的字符串返回给客户端作为握手依据。其中GUID是一个对于不识别WebSocket的网络端点不可能使用的字符串。
发送请求的要求:
  • 请求的WebSocket URI必须要是定义的有效的URI。
  • 如果客户端已经有一个WebSocket连接到远程服务器端,不论是否是同一个服务器,客户端必须要等待上一个连接关闭后才能发送新的连接请求,也就是同一客户端一次只能存在一个WebSocket连接。如果想同一个服务器有多个连接,客户端必须要串行化进行。如果客户端检测到多个到不同服务器的连接,应该限制一个最大连接数,在web浏览器中应该设定最多可以打开的标签页的数目。这样可以防止到远程服务器的DDOS攻击,但这是对到多个服务器的连接,如果是到同一个服务器连接,并没有数目限制。
  • 如果使用了代理服务器,那么客户端建立连接的时候需要告知代理服务器向目标服务器打开TCP连接。
  • 如果连接没有打开,一定是某一方出现错误,此时客户端必须要关闭再次连接的尝试。
  • 连接建立后,握手必须要是一个有效的HTTP请求
  • 请求的方式必须是GET,HTTP协议的版本至少是1.1
  • Upgrade字段必须包含而且必须是"websocket",Connection字段必须内容必须是“Upgrade”
  • Sec-Websocket-Version必须,而且必须是13

2、返回握手应答

服务器返回正确的相应头后,客户端验证后将建立连接,此时状态为OPEN。服务器响应头如下:
        HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

响应头握手过程中是服务器返回的是否同意握手的依据。

  • 首行返回的是HTTP/1.1协议版本和状态码101,表示变换协议(Switching Protocol)
  • Upgrade 和 Connection:这两个字段是服务器返回的告知客户端同意使用升级并使用websocket协议,用来完善HTTP升级响应
  • Sec-WebSocket-Accept:服务器端将加密处理后的握手Key通过这个字段返回给客户端表示服务器同意握手建立连接。
  • Sec-Websocket-Procotol:服务器选择的一个应用层协议。

上述响应头字段被客户端浏览器解析,如果验证到Sec-WebSocket-Accept字段的信息符合要求就会建立连接,同时就可以发送WebSocket的数据帧了。如果该字段不符合要求或者为空或者HTTP状态码不为101,就不会建立连接。

服务器端响应步骤:
  • 解析握手请求头:获取握手依据Key并进行处理,检测HTTP的GET请求和版本是否准确,Host字段是否有权限,Upgrade字段中websocket是一个与大小写无关的ASCII字符串,Connection字段是一个大小写无关的"Upgrade"ASCII字符串,Websocket协议版本必须为13,其他的关于Origin、Protocol和Extensions可选。
  • 发送握手响应头:检测是否是wss协议连接,如果是就是用TLS握手连接,否则就是普通连接。服务器可以添加额外的验证信息到客户端进行验证。当进行一系列验证之后,服务器必须返回一个有效的HTTP响应头。响应头中每一行一个字段,结束必须为“\r\n”,使用的ABNF语法。
除了上述必要头字段之外,其他的HTTP协议定义的字段都可以使用,如Set-Cookie等。

Websocket协议之握手连接的更多相关文章

  1. Websocket协议数据帧传输和关闭连接

    之前总结了关于Websocket协议的握手连接方式等其他细节,现在对socket连接建立后的数据帧传输和关闭细节总结. 一.数据帧格式 数据传输使用的是一系列数据帧,出于安全考虑和避免网络截获,客户端 ...

  2. 初识WebSocket协议

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

  3. WebSocket协议

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

  4. WebSocket --为什么引入WebSocket协议

    Browser已经支持http协议,为什么还要开发一种新的WebSocket协议呢?我们知道http协议是一种单向的网络协议,在建立连接后,它只允许Browser/UA(UserAgent)向WebS ...

  5. WebSocket协议入门介绍

    目录 目录 WebSocket协议是什么 WebSocket是应用层协议 WebSocket与Http的区别 为什么要使用WebSocket 如何使用WebSocket 客户端API 在客户端使用We ...

  6. WebSocket协议-基础篇

    本篇文章主要讲述以下几点: WebSocket协议出现的背景 WebSocket与HTTP WebSocket API WebSocket协议出现的背景 我们在上网过程中经常用到的是HTTP和HTTP ...

  7. WebSocket协议探究(序章)

    一 WebSocket协议基于HTTP和TCP协议 与往常一样,进入WebSocket协议学习之前,先进行WebSocket协议抓包,来一个第一印象. WebSocket能实现客户端和服务器间双向.基 ...

  8. WebSocket协议中文版

    WebSocket协议中文版 摘要 WebSocket协议实现在受控环境中运行不受信任代码的一个客户端到一个从该代码已经选择加入通信的远程主机之间的全双工通信.用于这个安全模型是通常由web浏览器使用 ...

  9. websocket协议握手详解

    最近使用tornado做长链接想着怎么着也要试试websocket协议吧.所以说干就干. 首先要知道websocket是基于http协议的,为什么这么说?因为从协议来说,websocket是借用了一部 ...

随机推荐

  1. AIR 移动设备上的存储控制

    File.documentsDirectory, File.userDirectory, File.desktopDirectory 等.可以保存大的数据,如图片,视屏,和临时文件.访问这些文件的全选 ...

  2. net.ipv4.tcp_tw_recycle

    原创 2016-03-07 CFC4N 运维帮 本文为翻译英文BLOG<Coping with the TCP TIME-WAIT state on busy Linux servers> ...

  3. 10个android开源项目

    http://www.51testing.com/?uid-116228-action-viewspace-itemid-244285 1.Android团队提供的示例项目 如果不是从学习Androi ...

  4. php常用系统函数

    首先纯html页要用meta标签声明编码   <meta http-equiv="Content-Type" content="text/html; charset ...

  5. Mechanism of Loading Resources

    Mechanism of Loading Resources 1. Distributed strategy 1.1. Developer guilde 1.2. Notes 2. Centraliz ...

  6. oracle 基础SQL语句 多表查询 子查询 分页查询 合并查询 分组查询 group by having order by

    select语句学习 . 创建表 create table user(user varchar2(20), id int); . 查看执行某条命令花费的时间 set timing on: . 查看表的 ...

  7. 转--xcode duplicate symbol问题

    遇到引用库重复定义的问题,需要解决.   项目需要,同时引用ZBar和QQ授权登录SDK,由于二者均使用了Base64处理数据,XCode编译时报错: duplicate symbol _base64 ...

  8. Android NDK调试方式之一: adb logcat

    查看程序执行过程中所打印的log信息,用于辅助调试排除代码错误. 一.采用NDK安装包下Samples/hello-jni工程做实验 1)修改jni/hello-jni.c文件 #include &l ...

  9. [置顶] c++类的继承(inheritance)

    在C++中,所谓"继承"就是在一个已存在的类的基础上建立一个新的类.已存在的类(例如"马")称为"基类(base class )"或&quo ...

  10. java.lang.ClassFormatError: Illegal UTF8 string in constant pool in class file Server/Request

    Linux服务器上,将本地编译好的文件上传后,Tomcat启动时报错: Exception in thread "Thread-2" java.lang.ClassFormatEr ...