webSocket原理探索

栏目: Html5 · 发布时间: 7年前

内容简介:Web Sockets的目标是在一个单独的持久连接上提供全双工、双向通信。在Javascript创建了Web Socket之后,会有一个HTTP请求发送到浏览器以发起连接。在取得服务器响应后,建立的连接会将HTTP升级从HTTP协议交换为WebSocket协议。由于WebSocket使用自定义的协议,所以URL模式也略有不同。未加密的连接不再是使用自定义协议而非HTTP协议的好处是,能够在客户端和服务器之间发送非常少量的数据,而不必担心HTTP那样字节级的开销。由于传递的数据包很小,所以WebSocket

本文概述

Web Sockets的目标是在一个单独的持久连接上提供全双工、双向通信。在Javascript创建了Web Socket之后,会有一个HTTP请求发送到浏览器以发起连接。在取得服务器响应后,建立的连接会将HTTP升级从HTTP协议交换为WebSocket协议。

由于WebSocket使用自定义的协议,所以URL模式也略有不同。未加密的连接不再是 http:// ,而是ws://;加密的连接也不是 https:// ,而是wss://。在使用WebSocket URL时,必须带着这个模式,因为将来还有可能支持其他的模式。

使用自定义协议而非HTTP协议的好处是,能够在客户端和服务器之间发送非常少量的数据,而不必担心HTTP那样字节级的开销。由于传递的数据包很小,所以WebSocket非常适合移动应用。

上文中只是对Web Sockets进行了笼统的描述,接下来的篇幅会对Web Sockets的细节实现进行深入的探索,本文不会涉及到大量的代码片段,但是会对相关的API和技术原理进行分析,相信大家读完下文之后再来看这段描述,会有一种豁然开朗的感觉。

一、WebSocket复用了HTTP的握手通道

“握手通道”是HTTP协议中客户端和服务端通过"TCP三次握手"建立的连接通道。客户端和服务端使用HTTP协议进行的每次交互都需要先建立这样一条“通道”,然后通过这条通道进行通信。我们熟悉的ajax交互就是在这样一个通道上完成数据传输的,下面是HTTP协议中建立“握手通道”的过程示意图:

webSocket原理探索

上文中我们提到:在Javascript创建了WebSocket之后,会有一个HTTP请求发送到浏览器以发起连接,然后服务端响应,这就是“握手“的过程,在这个握手的过程当中,客户端和服务端主要做了两件事情:

  1. 建立了一条连接“握手通道”用于通信(这点和HTTP协议相同,不同的是HTTP协议完成数据交互后就释放了这条握手通道,这就是所谓的“短连接”,它的生命周期是一次数据交互的时间,通常是毫秒级别的。)
  2. 将HTTP协议升级到WebSocket协议,并复用HTTP协议的握手通道,从而建立一条持久连接。

    说到这里可能有人会问:HTTP协议为什么不复用自己的“握手通道”,而非要在每次进行数据交互的时候都通过TCP三次握手重新建立“握手通道”呢?答案是这样的:虽然“长连接”在客户端和服务端交互的过程中省去了每次都建立“握手通道”的麻烦步骤,但是维持这样一条“长连接”是需要消耗服务器资源的,而在大多数情况下,这种资源的消耗又是不必要的,可以说HTTP标准的制定经过了深思熟虑的考量。到我们后边说到WebSocket协议数据帧时,大家可能就会明白,维持一条“持久连接”服务端和客户端需要做的事情太多了。

    说完了握手通道,我们再来看HTTP协议如何升级到WebSocket协议的。

二、HTTP协议升级为WebSocket协议

升级协议需要客户端和服务端交流,服务端怎么知道要将HTTP协议升级到WebSocket协议呢?它一定是接收到了客户端发送过来的某种信号。下面是我从谷歌浏览器中截取的“客户端发起协议升级请求的报文”,通过分析这段报文,我们能够得到有关WebSocket中协议升级的更多细节。

webSocket原理探索

首先,客户端发起协议升级请求。采用的是标准的HTTP报文格式,且只支持GET方法。下面是重点请求的首部的意义:
  1. Connection:Upgrade:表示要升级的协议
  2. Upgrade: websocket:表示要升级到websocket协议
  3. Sec-WebSocket-Version: 13:表示websocket的版本
  4. Sec-WebSocket-Key:UdTUf90CC561cQXn4n5XRg== :与Response Header中的响应首部Sec-WebSocket-Accept: GZk41FJZSYY0CmsrZPGpUGRQzkY=是配套的,提供基本的防护,比如恶意的连接或者无意的连接。

    其中Connection就是我们前边提到的,客户端发送给服务端的信号,服务端接受到信号之后,才会对HTTP协议进行升级。那么服务端怎样确认客户端发送过来的请求是否是合法的呢?在客户端每次发起协议升级请求的时候都会产生一个唯一码:Sec-WebSocket-Key。服务端拿到这个码后,通过一个算法进行校验,然后通过Sec-WebSocket-Accept响应给客户端,客户端再对Sec-WebSocket-Accept进行校验来完成验证。这个算法很简单:

1.将Sec-WebSocket-Key跟全局唯一的(GUID,[RFC4122])标识:258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接

2.通过SHA1计算出摘要,并转成base64字符串

258EAFA5-E914-47DA-95CA-C5AB0DC85B11这个字符串又叫“魔串",至于为什么要使用它作为Websocket握手计算中使用的字符串,这点我们无需关心,只需要知道它是RFC标准规定就可以了,官方的解析也只是简单的说此值不大可能被不明白WebSocket协议的网络终端使用。我们还是用世界上最好的语言来描述一下这个算法吧。

public function dohandshake($sock, $data, $key) {
        if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $data, $match)) {
            $response = base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
            $upgrade  = "HTTP/1.1 101 Switching Protocol\r\n" .
                "Upgrade: websocket\r\n" .
                "Connection: Upgrade\r\n" .
                "Sec-WebSocket-Accept: " . $response . "\r\n\r\n";
            socket_write($sock, $upgrade, strlen($upgrade));
            $this->isHand[$key] = true;
        }
    }
服务端响应客户端的头部信息和HTTP协议的格式是相同的,所以这里Sec-WebSocket-Accept字段后边的两个换行符是少不了的,这和我们使用curl工具模拟get请求是一个道理。这样展示结果似乎不太直观,我们使用命令行CLI来根据上图中的Sec-WebSocket-Key和握手算法来计算一下服务端返回的Sec-WebSocket-Accept是否正确:

webSocket原理探索

从图中可以看到,通过算法算出来的base64字符串和Sec-WebSocket-Accept是一样的。那么假如服务端在握手的过程中返回一个错误的Sec-WebSocket-Accept字符串会怎么样呢?当然是客户端会报错,连接会建立失败,大家最好尝试一下,例如将全局唯一标识符258EAFA5-E914-47DA-95CA-C5AB0DC85B11改为258EAFA5-E914-47DA-95CA-C5AB0DC85B12。

三、WebSocket的数据帧


以上所述就是小编给大家介绍的《webSocket原理探索》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

High Performance JavaScript

High Performance JavaScript

Nicholas C. Zakas / O'Reilly Media / 2010-4-2 / USD 34.99

If you're like most developers, you rely heavily on JavaScript to build interactive and quick-responding web applications. The problem is that all of those lines of JavaScript code can slow down your ......一起来看看 《High Performance JavaScript》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具