Tomcat中的WebSocket

什么是WebSocket

我们知道,Comet是在HTTP单向通信基础上模拟服务器与客户端浏览器的双向通讯,不同的Comet方案存在不同的缺陷,无论是跨浏览器层面还是规范限制。而且因为是一种模拟实现,所以它的效率并不高(如HTTP报头的开销,尤其发送消息较小的情况)。

基于这些原因,人们一直试图从规范角度寻找一种标准的替代方案。HTML5提供了一种全新的协议来解决这个问题,这就是WebSocket。它实现了客户端与服务器之间的全双工通信,可以更好的节省服务器资源及带宽以提供实时通讯。它建立在TCP之上,与HTTP一样通过TCP传输数据,而且同样使用HTTP的默认端口。WebSocket使得通过一种标准化的方式实现客户端与服务器之间全双工通信成为可能。

WebSocket是独立的基于TCP的协议,建立WebSocket链接时,客户端首先发送一个握手请求,服务器返回一个握手响应,握手为HTTP Upgrade请求 ,因此服务器可以通过HTTP端口进行处理,并将通信切换至WebSocket协议。握手成功后,客户端与服务器之间就可以基于WebSocket协议进行全双工通信了。

WebSocket与HTTP协议完全不同,它们之间的关系仅限于WebSocket的握手是通过HTTP协议的Upgrade请求完成的。WebSocket之所以如此设计,旨在不损害网络安全的前提下解决全双工通信的问题。

既然WebSocket是一种新的协议,那么它就同时需要客户端和服务器的支持。当前主流的浏览器均已支持WebSocket(Firefox 6、Safari 6、Chrome 14、Opera 12.10、IE 10)。服务器方面,主要的几款开源Servlet容器(Tomcat、Jetty、Undertow)都支持WebSocket。
WebSocket协议定义了ws://和wss://两个前缀来分别表示非加密和加密的链接。除去协议前缀外,其链接的具体语法格式与HTTP相同,如ws://127.0.0.1:8080/chat_demo/websocket/chat。

WebSocket握手请求格式如下:

GET /chat_demo/websocket/chat HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://127.0.0.1:8080
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: WBQn4/IgSnD3KjrxvvJpbg==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

“Upgrade:websocket”表明这是WebSocket请求,“Sec-WebSocket-Key”是客户端发送的一个base64编码的密文,要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”头信息作为应答。

服务器返回的握手响应如下:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: upafRZxTkaMPUBSr9VvuDXRambA=
Sec-WebSocket-Extensions: permessage-deflate

HTTP 101状态码表明服务端识别并切换为WebSocket协议,“Sec-WebSocket-Accept”是服务端采用与客户端一致的密钥计算出来的信息。

如果在与Web服务器集成的情况下使用使用WebSocket,通常需要Web服务器进行额外配置,具体可以参见各种Web服务器的配置方案,此处不再赘述:

Apache:http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
Nginx:https://www.nginx.com/blog/websocket-nginx/

既然WebSocket是HTML5新增的特性,那么在使用时我们就要考虑浏览器旧版本兼容的问题,这也是Comet方案尽管存在各种问题,但仍旧被采用的原因。

Tomcat的WebSocket实现

Tomcat自7.0.5版本开始支持WebSocket,并且实现了Java WebSocket规范(JSR356 ),而在7.0.5版本之前(7.0.2版本之后)则采用自定义API,即WebSocketServlet。本节我们仅介绍Tomcat针对规范的实现。

根据JSR356的规定,Java WebSocket应用由一系列的WebSocket Endpoint组成。Endpoint是一个Java对象,代表WebSocket链接的一端,对于服务端,我们可以视为处理具体WebSocket消息的接口,就像Servlet之于HTTP请求一样(不同之处在于Endpoint每个链接一个实例)。

我们可以通过两种方式定义Endpoint,第一种是编程式,即继承类javax.websocket.Endpoint并实现其方法。第二种是注解式,即定义一个POJO对象,为其添加Endpoint相关的注解。

Endpoint实例在WebSocket握手时创建,并在客户端与服务端链接过程中有效,最后在链接关闭时结束。Endpoint接口明确定义了与其生命周期相关的方法,规范实现者确保在生命周期的各个阶段调用实例的相关方法。

Endpoint的生命周期方法如下:

  • onOpen:当开启一个新的会话时调用。这是客户端与服务器握手成功后调用的方法。等同于注解@OnOpen。
  • onClose:当会话关闭时调用。等同于注解@OnClose。
  • onError:当链接过程中异常时调用。等同于注解@OnError。
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值