Tomcat实现WebSocket的⽅法
WebSocket协议属于HTML5标准,越来越多浏览器已经原⽣⽀持WebSocket,它能让客户端和服务端实现双向通信。在客户端和服务器端建⽴⼀条WebSocket连接后,服务器端消息可直接发送到客户端,从⽽打破传统的请求响应模式,避免了⽆意义的请求。⽐如传统的⽅式可能会使⽤AJAX不断请求服务器端,⽽WebSocket则可以直接发送数据到客户端且客户端不必请求。同时,由于有了浏览器的原⽣⽀持,编写客户端应⽤程序也变得更加便捷且不必依赖第三⽅插件。另外,WebSocket协议摒弃了HTTP协议繁琐的请求头,⽽是以数据帧的⽅式进⾏传输,效率更⾼。
图为WebSocket协议通信的过程,⾸先客户端会发送⼀个握⼿包告诉服务器端我想升级成WebSocket,不知道你服务器端是否同意,这时如果服务器端⽀持WebSocket协议则会返回⼀个握⼿包告诉客户端没问题,升级已确认。然后就成功建⽴起了⼀条WebSocket连接,该连接⽀持双向通信,并且使⽤WebSocket协议的数据帧格式发送消息。
握⼿过程需要说明下,为了让WebSocket协议能和现有HTTP协议Web架构互相兼容,所以WebSocket协议的握⼿要基于HTTP协议,⽐如客户端会发送类似如下的HTTP报⽂到服务器端请求升级为WebSocket协议,其中包含的Upgrade: websocket就是告诉服务器端我想升级协议:
GET ws://localhost:8080/hello HTTP/1.1
Origin: localhost:8080
Connection: Upgrade
Host: localhost:8080servlet和tomcat的关系
Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw==
Upgrade: websocket
Sec-WebSocket-Version: 13
此时如果服务器端⽀持WebSocket协议,则它会发送⼀个同意客户端升级协议的报⽂,具体报⽂类似如下,其中Upgrade: websocket就是告诉客户端我同意你升级协议:
HTTP/1.1 101 WebSocket Protocol Handshake
Date: Fri, 10 Feb 2016 17:38:18 GMT
Connection: Upgrade
Server: Kaazing Gateway
Upgrade: WebSocket
Sec-WebSocket-Accept: rLHCkw/SKsO9GAH/ZSFhBATDKrU=
完成如上握⼿后,HTTP协议连接就被打破,接下去则是开始使⽤WebSocket协议进⾏双⽅通信,这条连接还是原来的那条TCP/IP连接,端⼝也还是原来的80或443。
下⾯举⼀个Tomcat中编写WebSocket的简单例⼦:
public class HelloWebSocketServlet extends WebSocketServlet {
private static List<MessageInbound> socketList = new ArrayList<MessageInbound>();
protected StreamInbound createWebSocketInbound(String subProtocol,HttpServletRequest request){
return new WebSocketMessageInbound();
}
public class WebSocketMessageInbound extends MessageInbound{
protected void onClose(int status){
}
protected void onOpen(WsOutbound outbound){
socketList.add(this);
}
@Override
protected void onBinaryMessage(ByteBuffer message) throws IOException {
}
@Override
protected void onTextMessage(CharBuffer message) throws IOException {
for(MessageInbound messageInbound : socketList){
CharBuffer buffer = CharBuffer.wrap(message);
WsOutbound outbound = WsOutbound();
outbound.writeTextMessage(buffer);
outbound.flush();
}
}
}
}
这个Servlet必须要继承WebSocketServlet,接着创建⼀个继承MessageInbound的WebSocketMessageInbound类,在该类中填充onClose、onOpen、onBinaryMessage和onTextMessage等⽅法即可完成各个事件的逻辑,其中onOpen会在⼀个WebSocket连接建⽴时被调⽤,onClose会在⼀个WebSocket关闭时被调⽤,onBinaryMessage则是Binary⽅式下接收到客户端数据时被调⽤,onTextMessage则是Text⽅式下接收到客户端数据时被调⽤。上⾯⼀段代码实现了⼀个⼴播的效果。
按照上⾯的处理逻辑,Tomcat对WebSocket的集成就不会太难了,就是在处理请求时如果遇到WebSocket协议请求则做特殊处理,保持住连接并在适当的时机调⽤WebSocketServlet的MessageInbound的onClose、onOpen、onBinaryMessage和onTextMessage等⽅法。由于WebSocket⼀般建议在NIO模式下使⽤,所以看看NIO模式集成WebSocket协议。
如图,对于WebSocket的客户端连接被接收器接收后注册到NioChannel队列中,Poller组件不断轮休是否有NioChannel需要处理,如果有则经过处理管道后进到继承了WebSocketServlet的Servlet上,WebSocketServlet的doGet⽅法会处理WebSocket握⼿,告诉返回客户端同意升级协议。往后Poller继续不断轮休相关NioChannel,⼀旦发现是使⽤WebSocket协议的管道则会调⽤MessageInbound的相关⽅法,完成不同事件的处理,从⽽实现对WebSocket协议的⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。