郭晨 软件151 1531610114

WebSocket

  在HTML5中出现的WebSocket是一种比Comet还要新的反向Ajax技术,WebSocket启用了双向的全双工通信信道,许多浏览器(Firefox、Google Chrome和Safari)都已对此做了支持。连接是通过一个被称为WebSocket握手的HTTP请求打开的,其用到了一些特殊的报头。连接会保持在活动状态,你可以使用JavaScript来写入和接收数据,就像是在使用一个原始的TCP套接口一样。

  WebSocket URL的起始输入是ws://或是wss://(在SSL上)。

  图1中的时间线说明了使用WebSocket的通信。一个带有特定报头的HTTP握手被发送到了服务器端,接着在服务器端或是客户端就可以通过JavaScript来使用某种套接口(socket)了,这一套接口可被用来通过事件句柄异步地接收数据。

  图1. 使用WebSocket的反向Ajax

  本文可下载的源代码中有一个WebSocket例子,在运行该例子时,你应该会看到类似清单1的输出。其说明了客户端的事件是如何发生的,以及如何会立即在客户端显示出来。当客户端发送一些数据时,服务器端回应客户端的发送行为。

  清单1. JavaScript中的WebSocket例子

[client] WebSocket connection opened
[server] 1 events
[event] ClientID =0
[server] 1 events
[event] At Fri Jun 1721:12:01 EDT 2011
[server] 1 events
[event] From 0 : qqq
[server] 1 events
[event] At Fri Jun 1721:12:05 EDT 2011
[server] 1 events
[event] From 0 : vv

  通常情况下,在JavaScript中你会如清单2所说明的那样来使用WebSocket,如果你的浏览器支持它的话。

  清单2. JavaScript客户端例子

var ws = new WebSocket('ws://127.0.0.1:8080/async');
ws.onopen = function() {
    // 连接被打开时调用
};
ws.onerror = function(e) {
    // 在出现错误时调用,例如在连接断掉时
};
ws.onclose = function() {
    // 在连接被关闭时调用
};
ws.onmessage = function(msg) {
    // 在服务器端向客户端发送消息时调用
    // msg.data包含了消息
};
// 这里是如何给服务器端发送一些数据
ws.send('some data');
// 关闭套接口
ws.close();

  发送和接收的数据可以是任意类型的,WebSocket可被看成是TCP套接口,因此这取决于客户端和服务器端知道要来回发送的数据是哪种类型的。这里的例子发送的是JSON串。

  在JavaScript WebSocket对象被创建后,如果在浏览器的控制台(或是Firebug)中仔细看一下HTTP请求的话,你应该会看到WebSocket特有的报头。清单3给出了一个例子。

  清单3. HTTP请求和相应报头示例

Request URL:ws://127.0.0.1:8080/async
Request Method:GET
Status Code:101 WebSocket Protocol Handshake Request Headers
Connection:Upgrade
Host:127.0.0.1:8080
Origin:http://localhost:8080
Sec-WebSocket-Key1:1 &1~ 33188Yd]r8dp W75q
Sec-WebSocket-Key2:17; 229 *043M 8
Upgrade:WebSocket
(Key3):B4:BB:20:37:45:3F:BC:C7 Response Headers
Connection:Upgrade
Sec-WebSocket-Location:ws://127.0.0.1:8080/async
Sec-WebSocket-Origin:http://localhost:8080
Upgrade:WebSocket
(Challenge Response):AC:23:A5:7E:5D:E5:04:6A:B5:F8:CC:E7:AB:6D:1A:

  WebSocket握手使用所有的这些报头来验证并设置一个长生存期的连接,WebSocket的JavaScript对象还包含了两个有用的属性:

  ws.url:返回WebSocket服务器的URL
  ws.readyState:返回当前连接状态的值
  1. CONNECTING = 0
  2. OPEN = 1
  3. CLOSED = 2

  服务器端对WebSocket的处理要稍加复杂一些,现在还没有某个Java规范以一种标准的方式来支持WebSocket。要使用web容器(例如Tomcat或是Jetty)的WebSocket功能的话,你得把应用代码和容器特定的库紧密耦合在一起才能访问WebSocket的功能。

  示例代码的websocket文件夹中的例子使用的是Jetty的WebSocket API,因为我们使用的是Jetty容器。清单4 给出了WebSocket的处理程序。(本系列的第3部分会使用不同的后端WebSocket API。)

  清单4. Jetty容器的WebSocket处理程序

public final class ReverseAjaxServlet extends WebSocketServlet {
  @Override
  protected WebSocket doWebSocketConnect(HttpServletRequest request,String protocol) {
    return [...]
  }
}

  就Jetty来说,有几种处理WebSocket握手的方式,比较容易的一种方式是子类化Jetty的WebSocketServlet并实现doWebSocketConnect方法。该方法要求你返回Jetty的WebSocket接口的一个实例,你必须要实现该接口并返回代表了WebSocket连接的某种端点(endpoint)。清单5提供了一个例子。

  清单5. WebSocket实现示例

class Endpoint implements WebSocket {
Outbound outbound;
@Override
publicvoid onConnect(Outbound outbound) {
  this.outbound = outbound;
}
@Override
publicvoid onMessage(byte opcode, String data) {
  // 在接收到消息时调用
  // 你通常用到的就是这一方法
}
@Override
publicvoid onFragment(boolean more, byte opcode,byte[] data, int offset, int length) {
  // 在完成一段内容时,onMessage被调用
  // 通常不在这一方法中写入东西
}
@Override
publicvoid onMessage(byte opcode, byte[] data,int offset, int length) {
  onMessage(opcode, new String(data, offset, length));
}
@Override
publicvoid onDisconnect() {
  outbound =null;
}
}

  若要向客户端发送消息的话,你要向outbound中写入消息,如果清单6所示:

  清单6. 发送消息给客户端

if (outbound != null && outbound.isOpen()) {
  outbound.sendMessage('Hello World !');
}

  要断开并关闭到客户端的WebSocket连接的话,使用outbound.disconnect()。

  WebSocket是一种实现无延迟双向通信的非常强大的方法,Firefox、Google Chrome、Opera和其他的现代浏览器都支持这种做法。根据jWebSocket网站的说法:

  1. Chrome从4.0.249版本开始包含本地化的WebSocket。
  2. Safari 5.x包含了本地化的WebSocket。
  3. Firefox 3.7a6和4.0b1+包含了本地化的WebSocket。
  4. Opera从10.7.9.67开始包含了本地化的WebSocket。

  欲了解更多关于jWebSocket方面的内容,请查阅参考资料。

  优点

  WebSocket功能强大、双向、低延迟,且易于处理错误,其不会像Comet长轮询那样有许多的连接,也没有Comet流所具有的一些缺点。它的API也很容易使用,无需另外的层就可以直接使用,而Comet则需要一个很好的库来处理重连接、超时、Ajax请求、确认以及选择不同的传输(Ajax长轮询和jsonp轮询)。

  缺点

  WebSocket的缺点有这些:

  1. 是一个来自HTML5的新规范,还没有被所有的浏览器支持。

  2. 没有请求作用域(request scope),因为WebSocket是一个TCP套接口而不是一个HTTP请求,有作用域的请求服务,比如说Hibernate的SessionInViewFilter,就不太容易使用。Hibernate是一个持久性框架,其在HTTP请求的外围提供了一个过滤器。在请求开始时,其在请求线程中设定了一个上下文(包括事务和JDBC连接)边界;在请求结束时,过滤器销毁这一上下文。

  FlashSocket

  对于不支持WebSocket的浏览器来说,有些库能够回退到FlashSocket(经由Flash的套接口)上。这些库通常会提供同样的官方WebSocket API,但他们是通过把调用委托给一个包含在网站中的隐藏的Flash组件来实现的。

  优点

  FlashSocket透明地提供了WebSocket的功能,即使是在不支持HTML5 WebSocket的浏览器上也是如此。

  缺点

  FlashSocket有着下面的这些缺点:

  1. 其需要安装Flash插件(通常情况下,所有浏览器都会有该插件)。

  2. 其要求防火墙的843端口是打开的,这样Flash组件才能发出HTTP请求来检索包含了域授权的策略文件。如果843端口是不可到达的话,则库应该有回退动作或是给出一个错误,所有的这些处理都需要一些时间(最多3秒,这取决于库),而这会降低网站的速度。

  3. 如果客户端处在某个代理服务器的后面的话,到端口843的连接可能会被拒绝。

  WebSocketJS项目提供了一种桥接方式,其要求一个至少是10版本的Flash来为Firefox 3、Inernet Explorer 8和Internet Explorer 9提供WebSocket支持。

反向Ajax:WebSocket的更多相关文章

  1. Ajax、反向Ajax和WebSocket 概念

    Ajax 异步的JavaScript和XML(Asynchronous JavaScript and XML,Ajax),一种可通过JavaScript来访问的浏览器功能特性,其允许脚本向幕后的网站发 ...

  2. 反向Ajax,第2部分:WebSocket

    转自:http://kb.cnblogs.com/page/112616/ 前言 时至今日,用户期待的是可通过web访问快速.动态的应用.这一文章系列展示了如何使用反向Ajax(Reverse Aja ...

  3. 30分钟学会反向Ajax

    场景1:当有新邮件的时候,网页自动弹出提示信息而无需用户手动的刷新收件箱. 场景2:当用户的手机扫描完成页面中的二维码以后,页面会自动跳转. 场景3:在类似聊天室的环境中有任何人发言,所有登录用户都可 ...

  4. [转]30分钟学会反向Ajax

    原文链接:http://www.cnblogs.com/learnhow/p/5708364.html 场景1:当有新邮件的时候,网页自动弹出提示信息而无需用户手动的刷新收件箱. 场景2:当用户的手机 ...

  5. 反向Ajax之Socket.io

    1.什么是反向ajax? 传统的ajax的困惑? 新需求--当服务器端数据发生变化时,客户端(浏览器端)如何即时得到通知呢? 找一些实际的案例:客服系统.在线聊天 这类应用,有一个显著的特点: 数据并 ...

  6. 反向ajax实现

    在过去的几年中,web开发已经发生了很大的变化.现如今,我们期望的是能够通过web快速.动态地访问应用.在这一新的文章系列中,我们学习如何使用反 向Ajax(Reverse Ajax)技术来开发事件驱 ...

  7. 论反向ajax

    在讨论反向ajax之前,说一下我大二写的一个聊天程序,通过前端ajax不断向服务器发送请求(通过http连接),服务器进行一次数据库查询,然后返回结果,断开与服务器的链接(绝大部分都是无用的结果)来维 ...

  8. php开发客服系统(持久连接+轮询+反向ajax 转载 http://www.tuicool.com/articles/2mU7v2R)

    php开发客服系统( 下载源码 ) 用户端(可直接给客户发送消息) 客服端(点击用户名.即可给该用户回复消息) 讲两种实现方式: 一:iframe + 服务器推技术comet(反向ajax,即服务器向 ...

  9. 反向Ajax,实现服务器向客户端推送消息

    反向Ajax的基本概念是客户端不必从服务器获取信息,服务器会把相关信息直接推送到客户端.这样做的目的是解决Ajax传统Web模型所带来的一个限制:实时信息很难从技术上解决.原因是,客户端必须联系服务器 ...

随机推荐

  1. xcode10关于clang -lstdc++.6.0.9报错问题

    因为xcode10已经废弃了libstdc++.6.0.9这个库,所以只需要在你的工程中删除这个库,然后添加libc++这个库就可以了.别的没什么,如果xcode10报错mutable开头的,大部分是 ...

  2. Database First/Code First

  3. CSS3简单画出3d图形

    1.气球 2.泳圈 1.2两图实现代码分别如下: <html> <head> <meta charset="utf-8"> <meta h ...

  4. Java容器解析系列(7) ArrayDeque 详解

    ArrayDeque,从名字上就可以看出来,其是通过数组实现的双端队列,我们先来看其源码: /** 有自动扩容机制; 不是线程安全的; 不允许添加null; 作为栈使用时比java.util.Stac ...

  5. AsyncTask RejectedExecutionException 小结

    在使用Asynctask时,相信有些朋友会遇到以下RejectedExecutionException: Java.util.concurrent.RejectedExecutionException ...

  6. SharePoint Framework 基于团队的开发(五)

    博客地址:http://blog.csdn.net/FoxDave 升级SharePoint Framework项目 部署SharePoint自定制解决方案到生产环境并不意味着生命周期的结束,因为还有 ...

  7. Codeforces Round #479 (Div. 3) F. Consecutive Subsequence (简单dp)

    题目:https://codeforces.com/problemset/problem/977/F 题意:一个序列,求最长单调递增子序列,但是有一个要求是中间差值都是1 思路:dp,O(n)复杂度, ...

  8. Java EE设计模式(主要简单介绍工厂模式,适配器模式和模板方法模式)

    Java EE设计模式分为三种类型,共23种: 创建型模式:单例模式.抽象工厂模式.建造者模式.工厂模式.原型模式. 结构型模式:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式 ...

  9. ios ionic3 跳转第三方地图 xcode加入白名单

    之前我有篇随笔讲的是ionic3应用内跳转第三方地图应用的方法 忘了记录在ios内是需要把你用到的第三方地图应用加入跳转URL白名单内的 第三个是高德地图 iosamap 第四个是百度地图 baidu ...

  10. nginx 学习(一)

    今天不会nginx被怼了一顿.我必然不能忍,所以就赶忙来补充一下nginx知识!! nginx简介 nginx是一款高性能的http服务器,目前国内包括BAT在内的众多互联网企业均采用其作为反向代理服 ...