#WebSocket 是 html5 新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如 Chrome,Safrie,Firefox,Opera,IE 等等。

WebSocket API

首先看一段简单的 javascript 代码,该代码调用了 WebSockets 的 API。

var ws = new WebSocket(“ws://echo.websocket.org”);
ws.onopen = function(){ws.send(“Test!); };
ws.onmessage = function(evt){console.log(evt.data);ws.close();};
ws.onclose = function(evt){console.log(“WebSocketClosed!);};
ws.onerror = function(evt){console.log(“WebSocketError!);};

这份代码总共只有 5 行,现在简单概述一下这 5 行代码的意义。

第一行代码是在申请一个 WebSocket 对象,参数是需要连接的服务器端的地址,同 http 协议使用http://开头一样,WebSocket 协议的 URL 使用ws://开头,另外安全的 WebSocket 协议使用wss://开头。

第二行到第五行为 WebSocket 对象注册消息的处理函数,WebSocket 对象一共支持四个消息 onopen, onmessage, oncloseonerror

当 Browser 和 WebSocketServer 连接成功后,会触发 onopen 消息;

如果连接失败,发送、接收数据 失败或者处理数据出现错误,browser 会触发 onerror 消息;

当 Browser 接收到 WebSocketServer 发送过来的数据时,就会触发 onmessage 消息,参数 evt 中包含 server 传输过来的数据;

当 Browser 接收到 WebSocketServer 端发送的关闭连接请求时, 就会触发 onclose 消息。

我们可以看出 所有的操作都是采用消息的方式触发的,这样就不会阻塞 UI,使得 UI 有更快的响应时间,得到更好的用户体验

WebSocket 协议

WebSocket 协议是一种双向通信协议,它建立在 TCP 之上,同 http 一样通过 TCP 来传输数据,但是它和 http 最大的不同有两点:

  1. WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/UA 都能主动的向对方发送或接收数据,就像 Socket 一样,不同的是 WebSocket 是一种建立在 Web 基础上的一种简单模拟 Socket 的协议。

  2. WebSocket 需要通过握手连接,类似于 TCP 它也需要客户端和服务器端进行握手连接,连接成功后才能相互通信。

下面是一个简单的建立握手的时序图:

这里简单说明一下 WebSocket 握手的过程。

当 Web 应用程序调用 new WebSocket(url) 接口时,Browser 就开始了与地址为 url 的 WebServer 建立握手连接的过程。

  1. Browser 与 WebSocket 服务器通过 TCP 三次握手建立连接,如果这个建立连接失败,那么后面的过程就不会执行,Web 应用程序将收到错误消息通知。

  2. 在 TCP 建立连接成功后,Browser/UA 通过 http 协议传送 WebSocket 支持的版本号,协议的字版本号,原始地址,主机地址等等一些列字段给服务器端。

例如:

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
  1. WebSocket 服务器收到 Browser/UA 发送来的握手请求后,如果数据包数据和格式正确,客户端和服务器端的协议版本号匹配等等,就接受本次握手连接,并给出相应的数据回复,同样回复的数据包也是采用 http 协议传输。
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
  1. Browser 收到服务器回复的数据包后,如果数据包内容、格式都没有问题的话,就表 示本次连接成功,触发 onopen 消息,此时 Web 开发者就可以在此时通过 send 接口想服务器发送数据。

否则,握手连接失败,Web 应用程序会收到 onerror 消息,并且能知道连接失败的原因。

websocket 与 TCP,HTTP 的关系

WebSocket 与 http 协议一样都是基于 TCP 的,所以他们都是可靠的协议,Web 开发者调用的 WebSocket 的 send 函数在 browser 的实现中最终都是通过 TCP 的系统接口进行传输的。

WebSocket 和 Http 协议一样都属于应用层的协议,那么他们之间有没有什么关系呢?
答案是肯定 的,WebSocket 在建立握手连接时,数据是通过 http 协议传输的,正如我们上一节所看到的“GET/chat HTTP/1.1”,这里面用到的只是 http 协议一些简单的字段。但是在建立连接之后,真正的数据传输阶段是不需要 http 协议参与的。

websocket server

如果要搭建一个 Web 服务器,我们会有很多选择,市场上也有很多成熟的产品供我们应用,比如开源的 Apache,安装后只需简单的配置(或者默认配置)就可 以工作了。

但是如果想搭建一个 WebSocket 服务器就没有那么轻松了,因为 WebSocket 是一种新的通信协议,目前还是草案,没有成为标准,市场 上也没有成熟的 WebSocket 服务器或者 Library 实现 WebSocket 协议,我们就必须自己动手写代码去解析和组装 WebSocket 的数据 包。

要这样完成一个 WebSocket 服务器,估计所有的人都想放弃,幸好的是市场上有几款比较好的开源库供我们使用,比如 PyWebSocket,WebSocket-Node, LibWebSockets 等等,这些库文件已经实现了 WebSocket 数据包的封装和解析,我们可以调用这些接口,这在很大程度上减少了我们的工作量。如

github

websocket 是可以和 http 共用监听端口的,也就是它可以公用端口完成 socket 任务

关于 Socket 与 WebScoket

Socket 其实并不是一个协议。

它工作在 OSI 模型会话层(第 5 层),是为了方便大家直接使用更底层协议(一般是 TCP 或 UDP )而存在的一个抽象层。

最早的一套 Socket API 是 Berkeley sockets ,采用 C 语言实现。它是 Socket 的事实标准,POSIX sockets 是基于它构建的,多种编程语言都遵循这套 API,在 JAVA、Python 中都能看到这套 API 的影子。

Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。

在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面,对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。

主机 A 的应用程序要能和主机 B 的应用程序通信,必须通过 Socket 建立连接,而建立 Socket 连接必须需要底层 TCP/IP 协议来建立 TCP 连接。建立 TCP 连接需要底层 IP 协议来寻址网络中的主机。我们知道网络层使用的 IP 协议可以帮助我们根据 IP 地址来找到目标主机,但是一台主机上可能运行着多个应用程序,如何才能与指定的应用程序通信就要通过 TCP 或 UPD 的地址也就是端口号来指定。

这样就可以通过一个 Socket 实例唯一代表一个主机上的一个应用程序的通信链路了。

而 WebSocket 则不同,它是一个完整的 应用层协议,包含一套标准的 API 。

所以,从使用上来说,WebSocket 更易用,而 Socket 更灵活。

再简单来说, Socket 是一个应用程序接口,是抽象的,WebSocket 和 HTTP 是具体实现,

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐