非原创,版权归原作者所有http://www.cnblogs.com/shizhouyu/p/4975409.html

1、什么是WebSocket

WebSocket 是一种自然的全双工、双向、单套接字连接。使用WebSocket,你的HTTP 请求变成打开WebSocket 连接(WebSocket 或者WebSocket over TLS(TransportLayer Security,传输层安全性,原称“SSL”))的单一请求,并且重用从客户端到服务器以及服务器到客户端的同一连接。WebSocket 减少了延迟,因为一旦建立起WebSocket 连接,服务器可以在消息可用时发送它们。例如,和轮询不同,WebSocket只发出一个请求。服务器不需要等待来自客户端的请求。相似地,客户端可以在任何时候向服务器发送消息。相比轮询不管是否有可用消息,每隔一段时间都发送一个请求,单一请求大大减少了延迟。

2、WebSocket API

WebSocket API 使你可以通过Web,在客户端应用程序和服务器端进程之间建立全双工的双向通信。WebSocket 接口规定了可用于客户端的方法以及客户端与网络的交互方式。首先,你要调用WebSocket 构造函数(constructor),创建一个WebSocket 连接。构造函数返回WebSocket 对象实例。你可以监听该对象上的事件,这些事件告诉你何时连接打开,何时消息到达,何时连接关闭以及何时发生错误。你可以与WebSocket 对象交互,发送消息或者关闭连接。下面来研究WebSocket API 的各个方面。

3、WebSocket 构造函数

为了建立到服务器的WebSocket 连接,使用WebSocket 接口,通过指向一个代表所要连接端点的URL,实例化一个WebSocket对象。WebSocket 协议定义了两种URL 方案(URL scheme)—ws 和wss,分别用于客户端和服务器之间的非加密与加密流量。ws(WebSocket) 方案与HTTP URI 方案类似。wss(WebSocketSecure,WebSocket 安全)URI 方案表示使用传输层安全性(TLS,也叫SSL)的WebSocket 连接,使用HTTPS 采用的安全机制来保证HTTP 连接的安全。WebSocket 构造函数有一个必需的参数URL(指向连接目标的URL)和一个可选参数protocols(为了建立连接,服务器必须在其响应中包含的一个或一组协议名称)。在protocols 参数中可以使用的协议包括XMPP(eXtensible Messaging and PresenceProtocol, 可扩展消息处理现场协议)、SOAP(Simple ObjectAccess Protocol,简单对象访问协议)或者自定义协议。

  1. var ws = new WebSocket("ws://www.websocket.org");

带有协议支持的WebSocket 构造函数示例

  1. // Connecting to the server with multiple protocol choices
  2. var echoSocket = new WebSocket("ws://echo.websocket.org", ["com.kaazing.echo",
  3. "example.imaginary.protocol"])
  4. echoSocket.onopen = function(e) {
  5. // Check the protocol chosen by the server
  6. console.log(echoSocket.protocol);
  7. }

由于WebSocket 服务器ws://echo.websocket.org 只理解com.kaazing.echo 协议, 而不理解example.imaginary.protocol,该服务器在触发WebSocket open 事件的时候选择com.kaazing.echo 协议。使用数组为你提供了让应用程序对不同服务器使用不同协议的灵活性。

4、WebSocket 事件

WebSocket API 是纯事件驱动的。应用程序代码监听WebSocket对象上的事件,以便处理输入数据和连接状态的改变。WebSocket协议也是事件驱动的。客户端应用程序不需要轮询服务器来得到更新的数据。消息和事件将在服务器发送它们的时候异步到达。WebSocket 编程遵循异步编程模式,也就是说,只要WebSocket连接打开,应用程序就简单地监听事件。客户端不需要主动轮询服务器得到更多的信息。要开始监听事件,只要为WebSocket 对象添加回调函数。也可以使用addEventListener() DOM 方法为WebSocket 对象添加事件监听器。

WebSocket 对象调度4 个不同的事件:
open
message
error
close
和所有Web API 一样,可以用on< 事件名称> 处理程序属性

监听这些事件,也可以使用addEventListener(); 方法。

4.1、WebSocket 事件:open

一旦服务器响应了WebSocket 连接请求,open 事件触发并建立一个连接。open 事件对应的回调函数称作onopen。

  1. ws.onopen = function(e) {
  2. console.log("Connection open...");
  3. };

到open 事件触发时,协议握手已经完成,WebSocket 已经准备好发送和接收数据。如果应用程序接收到一个open 事件,那么可以确定WebSocket 服务器成功地处理了连接请求,并且同意与应用程序通信。

4.2、WebSocket messagess事件

WebSocket 消息包含来自服务器的数据。你也可能听说过组成WebSocket 消息的WebSocket 帧(Frame)。message 事件在接收到消息时触发,对应于该事件的回调函数是onmessage。

  1. ws.onmessage = function(e) {
  2. if(typeof e.data === "string"){
  3. console.log("String message received", e, e.data);
  4. } else {
  5. console.log("Other message received", e, e.data);
  6. }
  7. };

除了文本,WebSocket 消息还可以处理二进制数据,这种数据作为Blob 消息或者ArrayBuffer 消息处理。因为设置WebSocket 消息二进制数据类型的应用程序会影响二进制消息,所以必须在读取数据之前决定用于客户端二进制输入数据的类型。

  1. ws.binaryType = "blob";
  2. // Event handler for receiving Blob messages
  3. ws.onmessage = function(e) {
  4. if(e.data instanceof Blob){
  5. console.log("Blob message received", e.data);
  6. var blob = new Blob(e.data);
  7. }
  8. ws.binaryType = "arraybuffer";
  9. // Event handler for receiving ArrayBuffer messages
  10. ws.onmessage = function(e) {
  11. if(e.data instanceof ArrayBuffer){
  12. console.log("ArrayBuffer Message Received", + e.data);
  13. // e.data is an ArrayBuffer. Create a byte view of that object.
  14. var a = new Uint8Array(e.data);
  15. }
  16. };

4.3、 WebSocket 事件:error

error 事件在响应意外故障的时候触发。与该事件对应的回调函数为onerror。错误还会导致WebSocket 连接关闭。如果你接收一个error 事件,可以预期很快就会触发close 事件。close 事件中的代码和原因有时候能告诉你错误的根源。error事件处理程序是调用服务器重连逻辑以及处理来自WebSocket 对象的异常的最佳场所。

  1. ws.onerror = function(e){
  2. console.log('websocked error');
  3. handerError();
  4. }

4.4、 WebSocket 事件:close

close 事件在WebSocket 连接关闭时触发。对应于close 事件的回调函数是onclose。一旦连接关闭,客户端和服务器不再能接收或者发送消息。

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

WebSocket close 事件在连接关闭时触发,这可能有多种原因,比如连接失败或者成功的WebSocket 关闭握手。WebSocket 对象特性readyState 反映了连接的状态(2 为正在关闭,3 为已关闭)。

close 事件有3 个有用的属性(property),可以用于错误处理和恢复:wasClean、code 和error。wasClean 属性是一个布尔属性,表示连接是否顺利关闭。如果WebSocket 的关闭是对来自服务器的一个close 帧的响应,则该属性为true。如果连接是因为其他原因(例如,因为底层TCP 连接关闭)关闭,则该属性为false。code 和reason 属性表示服务器发送的关闭握手状态。这些属性和WebSocket.close() 方法中的code 和reason 参数一致。

5、WebSocket 方法

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

5.1、WebSocket 方法:send()

使用WebSocket 在客户端和服务器之间建立全双工双向连接后,就可以在连接打开时(也就是说,在调用onopen 监听器之后,调用onclose 监听器之前)调用send() 方法。使用send() 方法可以从客户端向服务器发送消息。在发送一条或者多条消息之后,可以保持连接打开,或者调用close() 方法终止连接。

  1. ws.send("Hello WebSocket!");

send() 方法在连接打开的时候发送数据。如果连接不可用或者关闭,它抛出一个有关无效连接状态的异常。人们开始使用WebSocket API 时常犯的一个错误是试图在连接打开之前发送消息。

  1. // Wait until the open event before calling send().
  2. var ws = new WebSocket("ws://echo.websocket.org")
  3. ws.onopen = function(e) {
  4. ws.send("Initial data");
  5. }

如果想发送消息响应另一个事件, 可以检查WebSocketreadyState 属性,并选择只在套接字打开时发送数据。

  1. function myEventHandler(data) {
  2. if (ws.readyState === WebSocket.OPEN) {
  3. // The socket is open, so it is ok to send the data.
  4. ws.send(data);
  5. } else {
  6. // Do something else in this case.
  7. //Possibly ignore the data or enqueue it.
  8. }
  9. }

除了文本(字符串)消息之外,WebSocket API 允许发送二进制数据,这对于实现二进制协议特别有用。这样的二进制协议可能是TCP 上层的标准互联网协议,这些协议的载荷可能是Blob 或ArrayBuffer。

5.2、WebSocket 方法:close()

使用close() 方法, 可以关闭WebSocket 连接或者终止连接尝试。如果连接已经关闭,该方法就什么都不做。在调用close() 之后,不能在已经关闭的WebSocket 上发送任何数据。可以向close() 方法传递两个可选参数:code(数字型的状态代码)和reason(一个文本字符串)。传递这些参数能够向服务器传递关于客户关闭连接原因的信息。

6、WebSocket 对象特性

可以使用多种WebSocket 对象特性提供关于WebSocket 对象的更多信息:readyState、bufferedAmount 和protocol。

6.1、WebSocket 对象特性:readyState

下表readyState 特性、取值和状态描述

特性常量 取值 状态
WebSocket.CONNECTING 0 连接正在进行中,但还未建立
WebSocket.OPEN 1 连接已经建立。消息可以在客户端和服务器之间传递
WebSocket.CLOSING 2 连接正在进行关闭握手
WebSocket.CLOSED 3 连接已经关闭,不能打开

6.2、WebSocket 对象特性:bufferedAmount

设计应用程序时,你可能想要检查发往服务器的缓冲数据量,特别是在客户端应用程序向服务器发送大量数据的时候。尽管调用send() 是立即生效的,但是数据在互联网上的传输却不是如此。浏览器将为你的客户端应用程序缓存出站数据,从而使你可以随时调用send(),发送任意数量的数据。然而,如果你想知道数据在网络上传送的速率,WebSocket 对象可以告诉你缓存的大小。你可以使用bufferedAmount 特性检查已经进入队列,但是尚未发送到服务器的字节数。这个特性报告的值不包括协议组帧开销或者操作系统、网络硬件所进行的缓冲。

代码展示一个使用bufferedAmount 特性每秒发送更新的例子。如果网络无法承受这一速率,它会相应地作出调整。

  1. // 10k max buffer size.
  2. var THRESHOLD = 10240;
  3. // Create a New WebSocket connection
  4. var ws = new WebSocket("ws://echo.websocket.org/updates");
  5. // Listen for the opening event
  6. ws.onopen = function () {
  7. // Attempt to send update every second.
  8. setInterval( function() {
  9. // Send only if the buffer is not full
  10. if (ws.bufferedAmount < THRESHOLD) {
  11. ws.send(getApplicationState());
  12. }
  13. }, 1000);
  14. };

对于限制应用向服务器发送数据的速率,从而避免网络饱和,bufferedAmount 特性很有用。

6.3、 WebSocket 对象特性:protocol

在前面关于WebSocket 构造函数的讨论中, 我们提到了protocol 参数,它让服务器知道客户端理解并可在WebSocket上使用的协议。WebSocket 对象的protocol 特性提供了另一条关于WebSocket 实例的有用信息。客户端和服务器协议协商的结果可以在WebSocket 对象上看到。protocol 特性包含在打开握手期间WebSocket 服务器选择的协议名,换句话说,protocol特性告诉你特定WebSocket 上使用的协议。protocol 特性在最初的握手完成之前为空,如果服务器没有选择客户端提供的某个协议,该特性保持空值。

例子:

  1. <!DOCTYPE html>
  2. <title>WebSocket Echo Client</title>
  3. <h2>Websocket Echo Client</h2>
  4. <div id="output"></div>
  5. <script>
  6. // Initialize WebSocket connection and event handlers
  7. function setup() {
  8. output = document.getElementById("output");
  9. ws = new WebSocket("ws://echo.websocket.org/echo");
  10. // Listen for the connection open event then call the sendMessage function
  11. ws.onopen = function(e) {
  12. log("Connected");
  13. sendMessage("这是发送的数据")
  14. }
  15. // Listen for the close connection event
  16. ws.onclose = function(e) {
  17. log("Disconnected: " + e.reason);
  18. }
  19. // Listen for connection errors
  20. ws.onerror = function(e) {
  21. log("Error ");
  22. }
  23. // Listen for new messages arriving at the client
  24. ws.onmessage = function(e) {
  25. log("Message received: " + e.data);
  26. // Close the socket once one message has arrived.
  27. ws.close();
  28. }
  29. }
  30. // Send a message on the WebSocket.
  31. function sendMessage(msg){
  32. ws.send(msg);
  33. log("Message sent");
  34. }
  35. // Display logging information in the document.
  36. function log(s) {
  37. var p = document.createElement("p");
  38. p.style.wordWrap = "break-word";
  39. p.textContent = s;
  40. output.appendChild(p);
  41. // Also log information on the javascript console
  42. console.log(s);
  43. }
  44. // Start running the example.
  45. setup();
  46. </script>
  47. </html>

7、WebSocket 浏览器兼容性检测

  1. if (window.WebSocket){
  2. console.log("This browser supports WebSocket!");
  3. } else {
  4. console.log("This browser does not support WebSocket.");
  5. }

8、在WebSocket 中使用HTML5 媒体

作为HTML5 和Web 平台的一部分,WebSocket API 可以很好地和所有HTML5 特性(feature)配合。这个API 所能发送和接收的数据类型广泛地用于传输应用程序数据和媒体。字符串当然可以表示XML 和JSON 等Web 数据格式。二进制类型可以和拖放(Drag-and-Drop)、FileReader、WebGL 和Web Audio API 等集成。我们来看看如何结合WebSocket 使用HTML5 媒体。代码清单展示了一个结合WebSocket 使用HTML5 媒体的完整客户端应用程序。

你可以根据这些代码创建自己的HTML 文件。

  1. <!DOCTYPE html>
  2. <title>WebSocket Image Drop</title>
  3. <h1>Drop Image Here</h1>
  4. <script>
  5. // Initialize WebSocket connection
  6. var wsUrl = "ws://echo.websocket.org/echo";
  7. var ws = new WebSocket(wsUrl);
  8. ws.onopen = function() {
  9. console.log("open");
  10. }
  11. // Handle binary image data received on the WebSocket
  12. ws.onmessage = function(e) {
  13. var blob = e.data;
  14. console.log("message: " + blob.size + " bytes");
  15. // Work with prefixed URL API
  16. if (window.webkitURL) {
  17. URL = webkitURL;
  18. }
  19. var uri = URL.createObjectURL(blob);
  20. var img = document.createElement("img");
  21. img.src = uri;
  22. document.body.appendChild(img);
  23. }
  24. // Handle drop event
  25. document.ondrop = function(e) {
  26. document.body.style.backgroundColor = "#fff";
  27. try {
  28. e.preventDefault();
  29. handleFileDrop(e.dataTransfer.files[0]);
  30. return false;
  31. } catch(err) {
  32. console.log(err);
  33. }
  34. }
  35. // Provide visual feedback for the drop area
  36. document.ondragover = function(e) {
  37. e.preventDefault();
  38. document.body.style.backgroundColor = "#6fff41";
  39. }
  40. document.ondragleave = function() {
  41. document.body.style.backgroundColor = "#fff";
  42. }
  43. // Read binary file contents and send them over WebSocket
  44. function handleFileDrop(file) {
  45. var reader = new FileReader();
  46. reader.readAsArrayBuffer(file);
  47. reader.onload = function() {
  48. console.log("sending: " + file.name);
  49. ws.send(reader.result);
  50. }
  51. }
  52. </script>
  53. </html>

文章参考:HTML5+WebSocket权威指南

webSocket学习与应用的更多相关文章

  1. WebSocket学习笔记IE,IOS,Android等设备的兼容性问

    WebSocket学习笔记IE,IOS,Android等设备的兼容性问 一.背景 公司最近准备将一套产品放到Andriod和IOS上面去,为了统一应用的开发方式,决定用各平台APP嵌套一个HTML5浏 ...

  2. WebSocket学习笔记——无痛入门

    WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报  分类: 物联网学习笔记(37)  版权声明:本文为博主原 ...

  3. WebSocket 学习笔记

    WebSocket 学习笔记 来自我的博客 因为项目原因需要用到双工通信,所以比较详细的学习了一下浏览器端支持的 WebSocket. 并记录一些遇到的问题. 简介 WebSocket 一般是指浏览器 ...

  4. WebSocket 学习(三)--用nodejs搭建服务器

    前面已经学习了WebSocket API,包括事件.方法和属性.详情:WebSocket(二)--API  WebSocket是基于事件驱动,支持全双工通信.下面通过三个简单例子体验一下. 简单开始 ...

  5. WebSocket学习总结

    一 .websocket 已解决      但是websocket延伸出来的网络编程还有好多知识点没有清理.主要的流程和实现方式已经大概了解清楚,下面从学习的进度思路来一点点复习.        网络 ...

  6. websocket学习和群聊实现

    WebSocket协议可以实现前后端全双工通信,从而取代浪费资源的长轮询.在此协议的基础上,可以实现前后端数据.多端数据,真正的实时响应.在学习WebSocket的过程中,实现了一个简化版群聊,过程和 ...

  7. java websocket学习

    引言: websocket,webservice傻傻分不清楚,都觉得是很高深的东西,理解中的webservice是一种协议,通信协议,类似http协议的那种,比如使用webservice协议调后台接口 ...

  8. WebSocket学习记录

    参考资料: Java后端WebSocket的Tomcat实现 基于Java的WebSocket推送 java WebSocket的实现以及Spring WebSocket 利用spring-webso ...

  9. WebSocket 学习--用nodejs搭建服务器

    最简单的socket服务端 var net = require("net"); server1 = net.createServer(function(client){ clien ...

  10. 【转载】Websocket学习

    首先是在Tomcat里面看到Websocket的演示.很有意思. http://localhost:8080/examples/websocket/index.xhtml 里面有: Echo exam ...

随机推荐

  1. FastDFS+Nginx部署详细教程

    本例使用到的所有tar和zip包地址:http://download.csdn.net/detail/corey_jk/9758664 本例中使用CentOS1.CentOS2两台机器实现. 1 GC ...

  2. toupper函数及一些小程序

    toupper 原型:extern int toupper(int c); 用法:#include <ctype.h> 功能:将字符c转换为大写英文字母 说明:如果c为小写英文字母,则返回 ...

  3. android学习8——获取view在屏幕上的绝对坐标

    获取view在屏幕上的绝对坐标在调试时候非常有用. 看如下代码 public class AbsolutePosActivity extends Activity { @Override public ...

  4. 【Zookeeper】源码分析之请求处理链(三)

    一.前言 在分析了PrepRequestProcessor处理器后,接着来分析SyncRequestProcessor,该处理器将请求存入磁盘,其将请求批量的存入磁盘以提高效率,请求在写入磁盘之前是不 ...

  5. libevent学习总结

    1. 信息隐藏:看*-internal.h文件 如bufferevent_private结构体在bufferevent_async.c中使用时: static inline struct buffer ...

  6. MySQL逻辑备份利器-mydumper

    关于mydumper的简介和下载请访问:https://launchpad.net/mydumper 简言之,mydumper是多线程逻辑备份,对于表和数据量很大的情况下,建议使用mydumper提高 ...

  7. YoMail 邮箱客户端的社会化之路,起于邮箱,不止于邮件

    你还记不记得上一次用邮箱处理私人事务是什么时候?从什么时候开始邮箱于你而言,唯一功能沦为了收取各种网站的验证信息? 电子邮件实际上非常适合于工作上使用,比起其他通信工具,或者社会化媒体,电子邮件在工作 ...

  8. 剑指offer编程题Java实现——面试题12打印1到最大的n位数

    题目:打印1到最大的n位数 输入数字n,按顺序打印输出从1到最大的n位十进制数,比如输入3,打印从1到999. 这道题考察的地方是如何表示大数问题.由于n是任意大的数组,如果n太大的话n位数就超过了l ...

  9. DTD验证XML文档

    DTD验证XML文档        1.DTD简介:DTD是Document Type Definition的缩写,即文档定义            1.1:DTD的内容包含:             ...

  10. v3学院带您一起学习FPGA

    本文为原创,转载请注明! 课程名称:双buffer乒乓操作项目概况:使用FPGA内部ram作为缓冲器,实现对外部数据流的缓存:为了提升数据的传输及处理速度,在此节课中将用到两个ram进行乒乓操作.结构 ...