WebSocket 快速入门

简介

WebSocket是基于TCP的一种新的网络协议,并在2011年被IETF定为标准的全双工通讯协议,它实现了客户端与服务器全双工通讯。javascript

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,容许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只须要完成一次握手,二者之间就直接能够建立持久性的链接,并进行双向数据传输。php

众所周知,在WebSocket出现以前,不少网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,而后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器须要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费不少的带宽等资源。而基于WebSocket 协议实现的客户端和服务器之简的通讯,能更好的节省服务器资源和带宽,而且可以更实时地进行通信。html

在这里插入图片描述

浏览器经过 JavaScript 向服务器发出创建 WebSocket 链接的请求,链接创建之后,客户端和服务器端就能够经过 TCP 链接直接交换数据。java

当获取 WebSocket 链接后,你能够经过 send() 方法来向服务器发送数据,并经过 onmessage 事件来接收服务器返回的数据。使用 WebSocket API 建立 的WebSocket 对象的示例以下:node

var Socket = new WebSocket(url, [protocol] );
复制代码

其中,第一个参数表示链接的URL,第二个参数 表示可接受的子协议。 Websocket 使用 ws 或 wss 的统一资源标志符,相似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket。如:python

ws://example.com/wsapi
wss://secure.example.com/
复制代码

Websocket 使用和 HTTP 相同的 TCP 端口,能够绕过大多数防火墙的限制。默认状况下,Websocket 协议使用 80 端口;运行在 TLS 之上时,默认使用 443 端口。nginx

下面是一个典型的Websocket握手请求实例:git

客户端请求github

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
复制代码

服务器回应web

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/
复制代码

下面是具体的解释:

  • Connection 必须设置 Upgrade,表示客户端但愿链接升级。

  • Upgrade 字段必须设置 Websocket,表示但愿升级到 Websocket 协议。

  • Sec-WebSocket-Key 是随机的字符串,服务器端会用这些数据来构造出一个 SHA-1 的信息摘要。把 “Sec-WebSocket-Key” 加上一个特殊字符串 “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,而后计算 SHA-1 摘要,以后进行 BASE-64编码,将结果作为 “Sec-WebSocket-Accept” 头的值,返回给客户端。如此操做,能够尽可能避免普通 HTTP 请求被误认为Websocket 协议。

  • Sec-WebSocket-Version 表示支持的 Websocket 版本。RFC6455 要求使用的版本是13,以前草案的版本均应当弃用。

  • Origin 字段是可选的,一般用来表示在浏览器中发起此 Websocket 链接所在的页面,相似于 Referer。可是,与Referer 不一样的是,Origin 只包含了协议和主机名称。

  • 其余一些定义在 HTTP 协议中的字段,如 Cookie 等,也能够在 Websocket 中使用。

websocket 与 socket

总的来讲:Socket 是传输控制层协议,WebSocket 是应用层协议。

软件通讯有七层结构,下三层结构偏向与数据通讯,上三层更偏向于数据处理,中间的传输层则是链接上三层与下三层之间的桥梁,每一层都作不一样的工做,上层协议依赖与下层协议。基于这个通讯结构的概念。

Socket 其实并非一个协议,是应用层与 TCP/IP 协议族通讯的中间软件抽象层,它是一组接口。当两台主机通讯时,让 Socket 去组织数据,以符合指定的协议。TCP 链接则更依靠于底层的 IP 协议,IP 协议的链接则依赖于链路层等更低层次。

属性

WebSocket具备以下属性:Socket.readyState和Socket.bufferedAmount。 readyState 其中,readyState表示链接状态,可能的值以下:

  • 0 - 表示链接还没有创建。
  • 1 - 表示链接已创建,能够进行通讯。
  • 2 - 表示链接正在进行关闭。
  • 3 - 表示链接已经关闭或者链接不能打开。

bufferedAmount bufferedAmount 表示已被 send() 放入正在队列中等待传输,可是尚未发出的 UTF-8 文本字节数。

事件

如下是 WebSocket 对象的相关事件。

  • open:链接创建时触发,使用方式Socket.onopen。
  • message:客户端接收服务端数据时触发,使用方式 Socket.onmessage。
  • error:通讯发生错误时触发,使用方式Socket.onerror。
  • close:链接关闭时触发,使用方式Socket.onclose。

方法

WebSocket主要的方法有send()和close()。

  • Socket.send():使用链接发送数据。
  • Socket.close():关闭链接。

实例

为了创建一个 WebSocket 链接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和一般的 HTTP 请求不一样,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"代表这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息而后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 链接就创建起来了,双方就能够经过这个链接通道自由的传递信息,而且这个链接会持续存在直到客户端或者服务器端的某一方主动的关闭链接。

编写客户端的 HTML 和 JavaScript

首先,编写一段客户端代码:

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>菜鸟教程(runoob.com)</title>
    
      <script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               alert("您的浏览器支持 WebSocket!");
               
               // 打开一个 web socket
               var ws = new WebSocket("ws://localhost:9998/echo");
                
               ws.onopen = function()
               {
                  // Web Socket 已链接上,使用 send() 方法发送数据
                  ws.send("发送数据");
                  alert("数据发送中...");
               };
                
               ws.onmessage = function (evt) 
               { 
                  var received_msg = evt.data;
                  alert("数据已接收...");
               };
                
               ws.onclose = function()
               { 
                  // 关闭 websocket
                  alert("链接已关闭..."); 
               };
            }
            
            else
            {
               // 浏览器不支持 WebSocket
               alert("您的浏览器不支持 WebSocket!");
            }
         }
      </script>
        
   </head>
   <body>
   
      <div id="sse">
         <a href="javascript:WebSocketTest()">运行 WebSocket</a>
      </div>
      
   </body>
</html>
复制代码

安装 pywebsocket

在执行以上程序前,咱们须要建立一个支持 WebSocket 的服务。从 pywebsocket 下载 mod_pywebsocket ,或者使用 git 命令下载。

git clone https://github.com/google/pywebsocket.git
复制代码

mod_pywebsocket 须要 python 环境支持,mod_pywebsocket 是一个 Apache HTTP 的 Web Socket扩展,安装步骤以下: 进入 pywebsocket 目录,执行以下命令:

$ python setup.py build
$ sudo python setup.py install
复制代码

而后,在pywebsocket/mod_pywebsocket 目录下执行如下命令开启服务。

sudo python standalone.py -p 9998 -w ../example/
复制代码

以上命令会开启一个端口号为 9998 的服务,使用 -w 来设置处理程序 echo_wsh.py 所在的目录。 如今咱们能够在 Chrome 浏览器打开前面建立的 runoob_websocket.html 文件。若是你的浏览器支持 WebSocket(), 点击"运行 WebSocket",你就能够看到整个流程各个步骤弹出的窗口,流程 Gif 演示:

在这里插入图片描述

在服务端开发方面,不一样的语言对于Websockt的支持还略有差别,下面是参考连接:

php - code.google.com/p/phpwebsoc…

jetty - jetty.codehaus.org/jetty/(版本7开…

netty - www.jboss.org/netty

ruby - github.com/gimite/web-…

Kaazing - web.archive.org/web/2010092…

Tomcat - tomcat.apache.org/(7.0.27支持we…

WebLogic - www.oracle.com/us/products…

node.js - github.com/Worlize/Web…

node.js - socket.io

nginx - nginx.com/

mojolicious - mojolicio.us/

python - github.com/abourget/ge…

Django - github.com/stephenmcd/…

erlang - github.com/ninenines/c…

相关文章
相关标签/搜索