郭晨 软件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. DevExpress v18.2新版亮点——DevExtreme篇(四)

    行业领先的.NET界面控件2018年第二次重大更新——DevExpress v18.2日前正式发布,本站将以连载的形式为大家介绍新版本新功能.本文将介绍了DevExtreme Complete Sub ...

  2. Linux监控

    第三十次课 Linux监控 目录 一. Linux监控平台介绍 二. zabbix监控介绍 三. 安装zabbix 四. 忘记Admin密码如何做 五. 主动模式和被动模式 六. 添加监控主机 七. ...

  3. oracle入门之分页查询

    oracle的分页查询共三种方法 1.根据ROWID来分页(速率一般) SQL>select * from emp where rowid in (select rid from (select ...

  4. tensorFlow小结

    1,才云科技的书 <实战G深度学习框架>是一本好书,我的练习基本上都在其示例上运行,网上查看的示例都类似. 2,windows下安装了anaconda,采用spyder来运行python ...

  5. Hacklab综合关

    没有注入到底能不能绕过登录 分值: 350 不是SQL注入 通关地址   不是注入,就先扫一下后台,发现在robots.txt后面有 访问一下,发现要先登陆,用burpsuit爆了好久都没有成功,最后 ...

  6. centos搭建ftp服务器的方法

    FTP操作 一.查看是否安装vsftpd rpm –qa|grep vsftpd 二.下载vsftpd yum install -y vsftpd 三.查看是否开启服务 service vsftpd ...

  7. CSS内嵌样式实现打字效果

    <style> *{margin:0;padding:0;} @keyframes typing { from { width: 0; } } @keyframes blink-caret ...

  8. 使用lua读文件并输出到stdin

    io.input("c:\\AudioCom.log") t= io.read("*all") io.write(t) 三行代码搞定,简洁的不像话 io.rea ...

  9. 运维ps语法---》ps、pstree、top、htop、nice、renice、kill、ulimit、w 和 who 和 whoami、pgrep、fg 和 bg、ipcs

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  10. Java的类型强制转换

    不说基本类型,没什么意思. 小括号的类型转换,在引用上,表示我坚定的确信,该未知类型一定是我转的类型,或者是我转的类型的子类. 这个转换逻辑和基本类型是不一致的.它不会进行任何具体的操作,只是一种标识 ...