WebSocket JavaScript API

WebSocket是HTML5提供的一种在单个TCP连接上进行全双工通信(双向通信)的协议,WebSocket使客户端和服务端之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

Web中已经有了HTTP协议,为什么还需要WebSocket协议呢?

由于HTTP协议有一个天生的缺陷:通信只能由客户端发起,因此HTTP协议做不到服务器主动向客户端推送信息。

HTTP 与 WebSocket

HTTP这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就必须采用轮询的方式。而轮询的效率低下且非常浪费资源,因为必须不停地连接或者让HTTP连接始终打开。此时,也就出现了WebSocket。

AJAX轮询与WebSocket

WebSocket协议诞生于2008年,2011年成为国际标准,主流浏览器均已经得到支持。WebSocket协议最大的特点是服务器可以主动的向客户端推送信息,客户端也可以主动的向服务器发送信息,它是真正的双向平等对话,属于服务器推送技术的一种。

WebSocket协议的特点

  • WebSocket协议建立在TCP协议之上,服务器实现比较容易。
  • WebSocket协议与HTTP协议有着良好的兼容性,默认端口是80和443,握手阶段采用HTTP协议因此不容易屏蔽,能通过各种HTTP代理服务器。
  • WebSocket数据格式比较轻量,性能开销较小,通信高效。
  • WebSocket可以发送文本也可以发送二进制数据
  • WebSocket没有同源限制,客户端可以与任意服务器通信。
  • WebSocket协议标识符是wswss,服务器地址直接是URL。
WebSocket

WebSocket API

WebSocket包含网络协议与API,让用户能够在客户端和服务端创建WebSocket连接。WebSocketAPI是使用WebSocket协议的接口,通过它来创建全双工通道以收发消息。

WebSocketAPI是纯事件驱动,一旦建立全双工链接,当服务端给客户端发送数据或资源时能自动发送状态改变的数据和通知。所以不需要为了状态的更新而去轮询服务器,只需要在客户端监听即可。

在WebSocket的API中,客户端和服务端只需要完成一次握手动作,然后客户端与服务端之间就会形成一条快速通道,两者之间就可以直接创建持久性的连接,并进行双向数据传输。

客户端通过JavaScript向服务端发起建立WebSocket连接的握手请求,当连接建立成功以后,客户端和服务端就可以通过TCP连接直接交换数据,当获取WebSocket连接后,可通过send()方法来向服务端发送数据,客户端通过onmessage事件来接收服务端返回的数据。

WebSocket协议本质

WebSocket协议本质上是一个基于TCP的协议 ,为了建立一个WebSocket连接,客户端浏览器首先要向服务器发起一个HTTP握手请求,这个请求和通常的HTTP请求有所不同,它包含了一些附加的头信息,其中会附加头信息Upgrade: WebSocket表明这是一个申请协议升级的HTTP请求。服务器解析这些附加的头信息后会产生应答信息并返回给客户端,客户端和服务器的WebSocket连接就会建立起来,双方就可以通过连接通道自由的传递信息,并且这个连接会持续存在直到客户端或服务器的某一方主动关闭连接。

客户端发送的典型WebSocket握手请求

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

服务器回应的WebSocket典型握手响应

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

WebSocket专有字段分析

  • Upgrade: websocket

Upgrade字段必须设置为websocket,表示客户端希望连接升级到websocket协议。

  • Connection: Upgrade

Connection必须设置为Upgrade,表示客户端希望连接升级

  • Sec-WebSocket-Key

Sec-WebSocket-Key是随机字符串,服务器会使用它来构造出一个SHA-1的信息摘要,将Sec-WebSocket-Key加上一个特殊的字符串,然后计算出SHA-1摘要,之后在进行BASE-64编码,最终结果作为Sec-WebSocket-Accept头的值返回给客户端。如此操作,可以尽量避免普通HTTP请求被误认为WebSocket协议。

  • Sec-WebSocket-Version

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

  • Origin

Origin字段是可选的,通常用来表示在浏览器中发起此WebSocket连接所在的页面,类似于Referer。但是与Referer不同的是,Origin只包含了协议和主机名称。

WebSocket与 Socket有什么区别呢?

在软件通信的七层架构中下三层结构偏向于数据通信,上三层偏向于数据处理,中间的传输层则是连接上三层和下三层之间的桥梁,每一层都做着不同的工作,上层协议 依赖于下层协议。

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

WebSocket则是一个典型的应用层协议,总体而言,Socket是传输控制层协议,WebSocket则是应用层协议。

构造函数

首先需要通过调用WebSocket的构造函数来创建WebSocket连接,构造函数会返回一个WebSocket实例,用来监听事件。

WebSocket构造函数需要传入一个URL参数和一个可选的协议参数

var ws = new WebSocket(url, [protocol]);
console.log(ws);
WebSocket对象

构造函数的第一个参数是URL,WebSocket协议定义了两种URL方案,WS和WSS分别代表了客户端和服务端之间未加密的通信。WS(WebSocket)类似于HTTP的URL,WSS(WebSocket Security)的URL表示连接是基于安全传输层(TLS/SSL),和HTTPS的连接使用的是同样的安全机制。URL参数需要以ws://wss://开头,如果URL存在语法错误构造函数会抛出异常。

构造函数的第二个参数是协议名称,是可选的,服务端和客户端使用的协议必须保持一致,这样收发消息时彼此才能理解。虽然可以定义一个或多个客户端使用的协议,但服务端只会选择一个来使用,一个客户端和一个服务端只能有一个协议,而且都必须基于WebSocket。协议名称参数支持XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或自定义协议。

WebSocket对象的属性

ws.readyState

只读属性readState表示当前连接状态,可选值包括

  • 0 WebSocket.CONNECTING 表示连接正在建立中但尚未建立
  • 1 WebSocket.OPEN 表示连接已经建立可以发送消息进行通信
  • 2 WebSocket.CLOSING表示连接正在进行关闭握手
  • 3 WebSocket.CLOSED 表示连接已经关闭或连接不能打开

ws.bufferedAmount

只读属性bufferedAmount表示已经被send()放入正在队列中等待传输,但还没有发出的UTF-8文本字节数。当需要检查传输数据大小时,尤其是客户端传输大量数据时,虽然send()方法会马上执行,但数据并不是马上传输。浏览器会缓存应用流出的数据,可以使用bufferedAmount属性检查已经进入队列但未被传输的数据大小。bufferedAmount值不包括协议框架、操作系统缓存和网络软件的开销。

例如:使用bufferedAmount属性每秒更新发送,如果网络不能处理这个频率会自动适应。

//判断浏览器是否支持WebSocket
if(window.WebSocket)
{
    console.log("This browser supports WebSocket");
}
else
{
    console.log("This browser does not support WebSocket");
}

//10K
var THRESHOLD = 10240;

//建立连接
var url = "ws://echo.websocket.org";
var ws = new WebSocket(url);

//监听握手请求
ws.onopen = function()
{
    setInterval(function(){
        //如果缓存未满时发送数据,使用bufferedAmount属性发送数据可以避免网络饱和。
        if(ws.bufferedAmount < THRESHOLD){
            ws.send(getApplicationState());
        }
    }, 1000);
}

ws.protocol

在构造函数中protocol参数会让服务器知道客户端使用的WebSocket协议,WebSocket对象的protocol属性是指最终服务器确定下来的协议名称,当服务器没有选择客户端提供的协议或在连接握手之前,此属性为空。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容

  • 原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-WebSo...
    敢梦敢当阅读 8,915评论 0 50
  • WebSocket 机制 WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更...
    勇敢的_心_阅读 2,269评论 0 4
  • 1.延展 可以定义私有属性和方法#import "MyClass.h" @interface MyClass ()...
    iOS小菜鸟阅读 200评论 0 1
  • 2009-06-25 17:11:25 从来没有迫害,也没有解救。美人,根本就是丛自我催眠的水仙。嗜睡是源于内心的...
    四两金阅读 135评论 0 1
  • 作者:尚小英 主题:27天的日常 DAY2 标题:迷茫的“老年人”2 正文:话说一时迷茫,一时爽,一直迷茫,一直爽...
    陈束阅读 133评论 0 1