Tomcat 实现WebSocket详细介绍

作者:汪洋之舟---seaboat 时间:2023-08-12 21:22:11 

Tomcat 如何实现WebSocket

WebSocket协议属于HTML5标准,越来越多浏览器已经原生支持WebSocket,它能让客户端和服务端实现双向通信。在客户端和服务器端建立一条WebSocket连接后,服务器端消息可直接发送到客户端,从而打破传统的请求响应模式,避免了无意义的请求。比如传统的方式可能会使用AJAX不断请求服务器端,而WebSocket则可以直接发送数据到客户端且客户端不必请求。同时,由于有了浏览器的原生支持,编写客户端应用程序也变得更加便捷且不必依赖第三方插件。另外,WebSocket协议摒弃了HTTP协议繁琐的请求头,而是以数据帧的方式进行传输,效率更高。

图为WebSocket协议通信的过程,首先客户端会发送一个握手包告诉服务器端我想升级成WebSocket,不知道你服务器端是否同意,这时如果服务器端支持WebSocket协议则会返回一个握手包告诉客户端没问题,升级已确认。然后就成功建立起了一条WebSocket连接,该连接支持双向通信,并且使用WebSocket协议的数据帧格式发送消息。

Tomcat 实现WebSocket详细介绍

握手过程需要说明下,为了让WebSocket协议能和现有HTTP协议Web架构互相兼容,所以WebSocket协议的握手要基于HTTP协议,比如客户端会发送类似如下的HTTP报文到服务器端请求升级为WebSocket协议,其中包含的Upgrade: websocket就是告诉服务器端我想升级协议:


 GET ws://localhost:8080/hello HTTP/1.1
 Origin: http://localhost:8080
 Connection: Upgrade
 Host: localhost:8080
 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){
     super.onClose(status);
     socketList.remove(this);      
   }
   protected void onOpen(WsOutbound outbound){
     super.onOpen(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 = messageInbound.getWsOutbound();
       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协议的支持。

Tomcat 实现WebSocket详细介绍

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

标签:Tomcat,WebSocket
0
投稿

猜你喜欢

  • Springboot使用POI实现导出Excel文件示例

    2021-09-22 08:18:31
  • Android编程中的消息机制实例详解

    2022-11-14 06:50:05
  • 详解通过JDBC进行简单的增删改查(以MySQL为例)

    2023-08-14 20:16:40
  • Spring中事务几个常见的问题解决

    2022-04-07 00:52:01
  • android 封装抓取网页信息的实例代码

    2021-11-28 09:40:32
  • Spring Cloud Ribbon的使用原理解析

    2021-10-11 02:03:01
  • C#微信开发(服务器配置)

    2023-07-18 17:42:01
  • springboot配置redis过程详解

    2022-10-13 12:41:30
  • C#中的委托、事件学习笔记

    2023-01-21 18:03:49
  • ImageSwitcher图像切换器的使用实例

    2022-10-29 13:16:02
  • Android使用Canvas对象实现刮刮乐效果

    2021-11-27 02:53:36
  • SpringBoot结合Vue实现投票系统过程详解

    2022-08-24 16:12:30
  • C#窗体程序实现全屏及取消全屏步骤

    2023-02-18 11:48:38
  • Springboot 整合 RabbitMQ 消息队列 详情

    2021-07-17 18:49:42
  • Java使用excel工具类导出对象功能示例

    2022-07-04 23:06:50
  • Java异常处理try catch的基本使用

    2023-11-24 05:04:38
  • 基于java构造方法Vector查找元素源码分析

    2023-11-29 04:33:30
  • C#装箱和拆箱的原理介绍

    2022-06-18 02:33:17
  • 你知道将Bean交给Spring容器管理有几种方式(推荐)

    2021-07-17 08:36:23
  • java使用正则抓取网页邮箱

    2022-12-02 10:30:30
  • asp之家 软件编程 m.aspxhome.com