WebSocket 介绍(二)-WebSocket API

这一章介绍如何用WebSocket API来控制协议和创建应用,运用http://websocket.org 提供的现有WebSocket服务器,我们可以收发消息、创建一些简单的WebSocket应用。一步一步的学习使用WebSocket API,最后我们会讨论浏览器的支持度和连通性。这一章的重点是WebSocket 协议在Web客户端的应用,在稍后的章节会介绍WebSocket协议以及其使用环境。

综述:

正如第一章提到的,WebSocket包含网络协议和API,让你能够在客户端和服务端创建WebSocket连接,第三章会详细讨论协议的细节,我们先看一下API。

WebSocket API其实就是一个使用WebSocket协议的接口,通过它来建立全双工通道来收发消息,简单易学,要连接远程服务器,只需要创建一个WebSocket对象实体,并传入一个服务端的URL。在客户端和服务端一开始握手的期间,http协议升级到WebSocket协议就建立了连接,底层都是TCP协议。一旦建立连接,通过WebSocket接口可以反复的发送消息。在你的代码里面,你可以使用异步事件监听连接生命周期的每个阶段。

WebSocket API是纯事件驱动,一旦建立全双工连接,当服务端给客户端发送数据或者资源,它能自动发送状态改变的数据和通知。所以你不需要为了状态的更新而去轮训Server,在客户端监听即可。在后续的章节我们会介绍更高级的协议,例如STOMP和XMPP,会学习不同的WebSocket API使用例子,然而现在,先仔细看看API。

入门:

首先,我们需要通过调用WebSocket构造函数来创建一个WebSocket连接,构造函数会返回一个WebSocket实例,可以用来监听事件。这些事件会告诉你什么时候连接建立,什么时候消息到达,什么时候连接关闭了,以及什么时候发生了错误。WebSocket协议定义了两种URL方案,WS和WSS分别代表了客户端和服务端之间未加密和加密的通信。WS(WebSocket)类似于Http URL,而WSS(WebSocket Security)URL 表示连接是基于安全传输层(TLS/SSL)和https的连接是同样的安全机制。

WebSocket的构造函数需要一个URL参数和一个可选的协议参数(一个或者多个协议的名字),协议的参数例如XMPP(Extensible Messaging and Presence Protocol)、SOAP(Simple Object Access Protocol)或者自定义协议。而URL参数需要以WS://或者WSS://开头,例如:ws://www.websocket.org,如果URL有语法错误,构造函数会抛出异常。

// Create new WebSocket connection
var ws = new WebSocket("ws://www.websocket.org");
//测试了下链接不上。

第二个参数是协议名称,是可选的,服务端和客服端使用的协议必须一致,这样收发消息彼此才能理解,你可以定义一个或多个客户端使用的协议,服务端会选择一个来使用,一个客服端和一个服务端之间只能有一个协议。当然都得基于WebSocket,WebSocket的重大好处之一就是基于WebSocket协议的广泛使用,让你的Web能够拥有传统桌面程序那样的能力,这个我们将在第三章第六节学习到。

言归正传,我们回到构造函数,在第一次握手之后,和协议的名称一起,客户端会发送一个Sec-WebSocket-Protocol 头,服务端会选择0个或一个协议,响应会带上同样的Sec-WebSocket-Protocol 头,否则会关闭连接。通过协议协商(Protocol negotiation ),我们可以知道给定的WebSocket服务器所支持的协议和版本,然后应用选择协议使用。

// Connecting to the server with one protocol called myProtocol
var ws = new WebSocket("ws://echo.websocket.org", "myProtocol");
//myProtocol 是假设的一个定义好的且符合标准的协议。

你可以传递一个协议的数组。

var echoSocket = new WebSocket("ws://echo.websocket.org", ["com.kaazing.echo","example.imaginary.protocol"])
//服务端会选择其中一个使用
echoSocket.onopen = function(e) {
// Check the protocol chosen by the server
console.log(echoSocket.protocol);
}

输出:com.kaazing.echo

协议这个参数有三种。

1.注册协议:根据RFC6455(WebSocket 协议)和IANA被官方注册的标准协议。例如 微软的SOAP。

详情可以参考:http://www.iana.org/assignments/websocket/websocket.xml

看到两个华为的

2.开放协议:被广泛使用的标注协议,例如XMPP和STOMP。但没有被正式注册。

3.自定义协议:自己编写和使用的WebSocket的协议。

协议会再后续章节给出详细介绍,下面先看事件、对象和方法以及实例。

WebSocket事件:

WebSocket API是纯事件驱动,通过监听事件可以处理到来的数据和改变的链接状态。客户端不需要为了更新数据而轮训服务器。服务端发送数据后,消息和事件会异步到达。WebSocket编程遵循一个异步编程模型,只需要对WebSocket对象增加回调函数就可以监听事件。你也可以使用addEventListener()方法来监听。而一个WebSocket对象分四类不同事件。

open:

一旦服务端响应WebSocket连接请求,就会触发open事件。响应的回调函数称为onopen。

// Event handler for the WebSocket connection opening
ws.onopen = function(e) {
console.log("Connection open...");
};

open事件触发的时候,意味着协议握手结束,WebSocket已经准备好收发数据。如果你的应用收到open事件,就可以确定服务端已经处理了建立连接的请求,且同意和你的应用通信。

Message:

当消息被接受会触发消息事件,响应的回调函数叫做onmessage。如下:

// 接受文本消息的事件处理实例:
ws.onmessage = function(e) {
if(typeof e.data === "string"){
console.log("String message received", e, e.data);
} else {
console.log("Other message received", e, e.data);
}
};

除了文本消息,WebSocket消息机制还能处理二进制数据,有Blob和ArrayBuffer两种类型,在读取到数据之前需要决定好数据的类型。

// 设置二进制数据类型为blob(默认类型)
ws.binaryType = "blob";
// Event handler for receiving Blob messages
ws.onmessage = function(e) {
if(e.data instanceof Blob){
console.log("Blob message received", e.data);
var blob = new Blob(e.data);
}
};
//ArrayBuffer
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
if(e.data instanceof ArrayBuffer){
console.log("ArrayBuffer Message Received", + e.data);
// e.data即ArrayBuffer类型
var a = new Uint8Array(e.data);
}
};

Error

如果发生意外的失败会触发error事件,相应的函数称为onerror,错误会导致连接关闭。如果你收到一个错误事件,那么你很快会收到一个关闭事件,在关闭事件中也许会告诉你错误的原因。而对错误事件的处理比较适合做重连的逻辑。

//异常处理
ws.onerror = function(e) {
console.log("WebSocket Error: " , e);
//Custom function for handling errors
handleErrors(e);
};

Close

不言而喻,当连接关闭的时候回触发这个事件,对应onclose方法,连接关闭之后,服务端和客户端就不能再收发消息。

WebSocket的规范其实还定义了ping和pong 架构(frames),可以用来做keep-alive,心跳,网络状态查询,latency instrumentation(延迟仪表?),但是目前 WebSocket API还没有公布这些特性,尽管浏览器支持了ping,但不会触发ping事件,相反,浏览器会自动响应pong,第八章会将更多关于ping和pong的细节。

当然你可以调用close方法断开与服务端的链接来触发onclose事件,

ws.onclose = function(e) {
console.log("Connection closed", e);
};

连接失败和成功的关闭握手都会触发关闭事件,WebSocket的对象的readyState属性就代表连接的状态(2代表正在关闭,3代表已经关闭)。关闭事件有三个属性可以用来做异常处理和重获: wasClean,code和reason。wasClean是一个bool值,代表连接是否干净的关闭。   如果是响应服务端的close事件,这个值为true,如果是别的原因,比如因为是底层TCP连接关闭,wasClean为false。code和reason代表关闭连接时服务端发送的状态,这两个属性和给入close方法的code和reason参数是对应的,稍后会描述细节。

WebSocket 方法:

WebSocket 对象有两个方法:send()和close()

send():

一旦在服务端和客户端建立了全双工的双向连接,可以使用send方法去发送消息,

//发送一个文本消息
ws.send("Hello WebSocket!");

当连接是open的时候send()方法传送数据,当连接关闭或获取不到的时候回抛出异常。一个通常的错误是人们喜欢在连接open之前发送消息。如下所示:

// 这将不会工作
var ws = new WebSocket("ws://echo.websocket.org")
ws.send("Initial data");

正确的姿势如下,应该等待open事件触发后再发送消息。

var ws = new WebSocket("ws://echo.websocket.org")
ws.onopen = function(e) {
ws.send("Initial data");
}

如果想通过响应别的事件去发送消息,可以检查readyState属性的值为open的时候来实现。

function myEventHandler(data) {
if (ws.readyState === WebSocket.OPEN) {
//open的时候即可发送
ws.send(data);
} else {
// Do something else in this case.
//Possibly ignore the data or enqueue it.
}
}

发送二进制数据:

// Send a Blob
var blob = new Blob("blob contents");
ws.send(blob);
// Send an ArrayBuffer
var a = new Uint8Array([8,6,7,5,3,0,9]);
ws.send(a.buffer);

Blob对象和JavaScript File API一起使用的时候相当有用,可以发送或接受文件,大部分的多媒体文件,图像,视频和音频文件。这一章末尾会结合File API提供读取文件内容来发送WebSocket消息的实例代码。

close()

使用close方法来关闭连接,如果连接以及关闭,这方法将什么也不做。调用close方法只后,将不能发送数据。

ws.close();

close方法可以传入两个可选的参数,code(numerical)和reason(string),以告诉服务端为什么终止连接。第三章讲到关闭握手的时候再详细讨论这两个参数。

// 成功结束会话
ws.close(1000, "Closing normally");
//1000是状态码,代表正常结束。

WebSocket 属性

WebSocket对象有三个属性,readyState,bufferedAmount和Protocol。

readyState:

WebSocket对象通过只读属性readyState来传达连接状态,它会更加连接状态自动改变。下表展示了readyState属性的四个不同的值。


属性


状态

WebSocket.CONNECTING
0
连接正在进行,但还没有建立

WebSocket.OPEN

1
连接已经建立,可以发送消息。

WebSocket.CLOSING

2
连接正在进行关闭握手

WebSocket.CLOSED

3
连接已经关闭或不能打开

了解当前连接的状态有助于我们调试。

bufferedAmount:

有时候需要检查传输数据的大小,尤其是客户端传输大量数据的时候。虽然send()方法会马上执行,但数据并不是马上传输。浏览器会缓存应用流出的数据,你可以使用bufferedAmount属性检查已经进入队列但还未被传输的数据大小。这个值不包含协议框架、操作系统缓存和网络软件的开销。

下面这个例子展示了如何使用bufferedAmount属性每秒更新发送。如果网络不能处理这个频率,它会自适应。

// 10k
var THRESHOLD = 10240;
//建立连接
var ws = new WebSocket("ws://echo.websocket.org");
// Listen for the opening event
ws.onopen = function () {
setInterval( function() {
//缓存未满的时候发送
if (ws.bufferedAmount < THRESHOLD) {
ws.send(getApplicationState());
}
}, 1000);
};
//使用bufferedAmount属性发送数据可以避免网络饱和。

protocol:

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

完整实例

现在我们已经过了一遍WebSocket的构造函数、事件、属性和方法,接下来通过一个完整的实例来学习WebSocket API。实例使用“Echo”服务器:ws://echo.websocket.org,它能够接受和返回发过去的数据。这样有助于理解WebSocket API是如何和服务器交互的。

首先,我们先建立连接,让页面展示客户端连接服务端的信息,然后发送、接受消息,最后关闭连接。

  <h2>Websocket Echo Client</h2>
    <div id="output"></div>
     // 初始化连接和事件
        function setup() {
            output = document.getElementById("output");
            ws = new WebSocket("ws://echo.websocket.org/echo");
            // 监听open
            ws.onopen = function (e) {
                log("Connected");
                sendMessage("Hello WebSocket!");
            }
            // 监听close
            ws.onclose = function (e) {
                log("Disconnected: " + e.reason);
            }
            //监听errors
            ws.onerror = function (e) {
                log("Error ");
            }
            // 监听 messages
            ws.onmessage = function (e) {
                log("Message received: " + e.data);
                //收到消息后关闭
                ws.close();
            }
        }
        // 发送消息
        function sendMessage(msg) {
            ws.send(msg);
            log("Message sent");
        }
        // logging
        function log(s) {
            var p = document.createElement("p");
            p.style.wordWrap = "break-word";
            p.textContent = s;
            output.appendChild(p);
            // Also log information on the javascript console
            console.log(s);
        }
        // Start
        setup();

时间: 2024-11-05 20:40:22

WebSocket 介绍(二)-WebSocket API的相关文章

基于构建实时WEb应用的HTML5 WebSocket协议&lt;二&gt;

前面说了那么多的理论,我们来看下代码学习. WebSocketAPI简介 首先看一段简单的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(

WebSocket介绍,与Socket的区别

WebSocket介绍与原理 WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex).一开始的握手需要借助HTTP请求完成. --百度百科 目的:即时通讯,替代轮询 网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等.按照以往的技术能力通常是采用轮询.Comet技术解决. HTTP协议是非持久化的,单向的网络协议,在建立连接后只允许浏览器向服务器发出请求后,服务器才能返回相应的数据.当需要即时通讯时,通过轮询在特定的时间间隔

Jetty开发指导:WebSocket介绍

WebSocket是一个新的基于HTTP的双向通讯的协议. 它是基于低级别的框架协议.使用UTF-8 TEXT或者BINARY格式传递信息. 在WebSocket中的单个信息能够是不论什么长度(然而底层框架有单帧63bits的限制). 发送的信息数量不受限制. 信息被持续的发送,基础协议不支持交叉的信息. 一个WebSocket连接经历一些主要的状态改变: 1)CONNECTING:HTTP升级到WebSocket正在进行中 2)OPEN:HTTP升级成功,而且socket如今打开并准备读/写

WebSocket介绍与原理

WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样: WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信. 目的:即时通讯,替代轮询 连接过程 -- 握手过程 浏览器.服务器建立TCP连接,三次握手.这是通信的基础,传输控制层,若失败后续都不执行. TCP连接成功后,浏览器通过HTTP协议向服务器传送WebSocket支持的

学习WebSocket一(WebSocket初识)

Java EE 7 去年刚刚发布了JSR356规范,使得WebSocket的Java API得到了统一,Tomcat从7.0.47开始支持JSR356,这样一来写WebSocket的时候,所用的代码都是可以一样的.今天终于体验了一把Tomcat发布的WebSocket,用着很爽,下面把这一历程分享给大家. 关键词:WebSocket, Tomcat 前提:使用Tomcat7.0.47,Firefox25.0.0.5046 首先Tomcat7.0.47自带WebSocket的示例程序,有两种版本,

Quartz教程二:API,Job和Trigger

原文链接 | 译文链接 | 翻译:nkcoder | 校对:方腾飞 本系列教程由quartz-2.2.x官方文档翻译.整理而来,希望给同样对quartz感兴趣的朋友一些参考和帮助,有任何不当或错误之处,欢迎指正:有兴趣研究源码的同学,可以参考我对quartz-core源码的注释(进行中). Quartz API Quartz API核心接口有: Scheduler – 与scheduler交互的主要API: Job – 你通过scheduler执行任务,你的任务类需要实现的接口: JobDeta

Avaya Exrience Portal(AEP)基础介绍 二(四大组件总结)

什么是Avaya Exrience Portal(AEP)? 1:提供语音(或者多媒体)自动化用户体验的软件平台:  2:基于标准的VXML(定义了如何使用语音识别.语音合成.互联网访问.数据库访问.语音文件播放.DTMF输入等功能开发一个完整的语音应用系统.)和CCXML(它基于XML定义了一系列开放标准的呼叫控制API)的应用:  3:支持多媒体处理:  4:完全基于Web架构:  5:支持TTS文语转换和语音识别技术:     2)AEP包含的组件   EPM:AEP集成的管理,报表,监控

学习WebSocket(一):Spring WebSocket的简单使用

1.什么是websocket? WebSocket协议定义了一种web应用的新功能,它实现了服务器端和客户端的全双工通信.全双工通信即通信的双方可以同时发送和接收信息 的信息交互方式.它是继Java applets, XMLHttpRequest, Adobe Flash, ActiveXObject等使web应用更具交互性的新技术. 在实现连线过程中,浏览器和服务器通过TCP三次握手建立连接. 如果和服务器连接成功后,浏览器通过HTTP发送握手请求,如果服务器同意握手连接,客户端和服务端之后就

linux程序分析工具介绍(二)—-ldd,nm

本文要介绍的ldd和nm是linux下,两个用来分析程序很实用的工具.ldd是用来分析程序运行时需要依赖的动态库的工具:nm是用来查看指定程序中的符号表相关内容的工具.下面通过例子,分别来介绍一下这两个工具: 1. ldd, 先看下面的例子, 用ldd查看cs程序所依赖的动态库: [email protected]:~/Public$ ldd cs linux-gate.so.1 => (0xffffe000) libz.so.1 => /lib/libz.so.1 (0xb7f8c000)