# 利刃出鞘_Tomcat 核心原理解析(十一)-- WebSocket -- 1

2024-09-02 15:52

本文主要是介绍# 利刃出鞘_Tomcat 核心原理解析(十一)-- WebSocket -- 1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

利刃出鞘_Tomcat 核心原理解析(十一)-- Tomcat 附加功能 WebSocket – 1

一、Tomcat专题 - WebSocket - 介绍

1、Tomcat 附加功能:websocket 介绍

1)websocket :是 HTML5 新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,
比如说,服务器可以在任意时刻发送消息给浏览器。

2)为什么传统的 HTTP 协议不能做到 websocket 实现的功能?

  • 这是因为 HTTP 协议是一个请求-响应协议,请求必须先由浏览器发给服务器服务器才能响应这个请求,再把数据发送给浏览器。
    换句话说,浏览器不主动请求,服务器是没法主动发数据给浏览器的,

  • 这样一来,要在浏览器中搞一个实时聊天,或者在线多人游戏的话就没法实现了,只能借助 Elash 这些插件,

3)也有人说,HTTP 协议其实也能实现啊,比如用轮询或者 comet。

  • 轮询:是指浏览器通过 Javascript 启动一个定时器,然后以固定的间隔给服务器发请求,询问服务器有没有新消息。
    这个机制的缺点一是实时性不够,二是频繁的请求会给服务器带来极大的压力。

  • comet 本质上也是轮询,但是在没有消息的情况下,服务器先拖一段时间,等到有消息了再回复,这个机制暂时地解决了实时性问题,

但是它带来了新的问题:

以多线程模式运行的服务器会让大部分线程大部分时间都处于挂起状态,极大地浪费服务器资源。
另外,一个 HTTP 连接在长时间没有数据传输的情况下,链路上的任何一个网关都可能关闭这个连接,
而网关是我们不可控的,这就要求 comet 连接必须定期发一些 ping 数据表示连接“正常工作"。

tomcat-67.png

2、以上两种机制都治标不治本,所以,HTML5 推出了 websocket 标准,让浏览器和服务器之间可以建立无限制的全双工通信,任何一方都可以主动发消息给对方。websocket 并不是全新的协议,而是利用了 HTTP 协议来建立连接。

tomcat-68.png

3、websocket 连接是如何创建的。

1)首先,websocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

tomcat-69.png

2)该请求和普通的HTTP请求有几点不同:

  • 1.GET请求的地址不是类似 http://,而是以 ws:// 开头的地址;
  • 2.请求头 connection:upgrade 和 请求头 upgrade:websocket 表示这个连接将要被转换为 websocket 连接;
  • 3.sec-websocket-Key 是用于标识这个连接, 是一个BASE64编码的密文,要求服务端响应一个对应加密的sec-websocket-Accept头信息作为应答。
  • 4.sec-websocket-version 指定了 websocket 的协议版本;
  • 5.HTTP101 状态码表明服务端已经识别并切换为 Websocket 协议,sec-websocket-Accept 是服务端与客户端一致的秘钥计算出来的信息。

二、Tomcat专题 - WebSocket - Tomcat的支持

1、Tomcat 的 Websocket

Tomcat 的 7.0.5 版本开始支持 websocket,并且实现了 Java websocket 规范(JSR356),而在7.0.5版本之前(7.0.2之后)则采用自定义 API,即 websocketservlet 实现。

2、Java websocket 应用由一系列的 nebsocketEndpoint 组成。Endpoint 是一个 Java 对象,代表 websocket 链接的一端,对于服务端,可以视为处理具体 websocket 消息的接口,就像 servlet 之与 http 请求一样。

3、可以通过两种方式定义 Endpoint:

1)第一种是编程式,即继承类 javax.websocket.Endpoint 并实现其方法。

2)第二种是注解式,即定义一个POJO,并添加 @serverEndpoint 相关注解。

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

方法含义描述注解
onOpen当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法。@onopen
onClose当会话关闭时调用。@onClose
onError当连接过程中异常时调用。@onError

5、编程式 和 注解式 接收和发送消息。

  • 编程式通过为 session 添加 Messagexandler 消息处理器来接收消息。
  • 采用注解方式定义 Endpoint 时,可以通过 @onMessage 注解指定接收消息的方法。发送消息则由 RemoteEndpoint 完成,其实例由 session 维护。
  • 根据使用情况, 可以通过 session.getBasicRemote 获取同步消息发送的实例,然后调用其 sendxxx() 方法就可以发送消息,可以通过 session.getAsyncRemote 获取异步消息发送实例。

6、…\apache-tomcat-8.5.42-src\java\javax\websocket\Endpoint.java 类,源码:


package javax.websocket;public abstract class Endpoint {public abstract void onOpen(Session session, EndpointConfig config);public void onClose(Session session, CloseReason closeReason) {// NO-OP by default}public void onError(Session session, Throwable throwable) {// NO-OP by default}
}

三、 Tomcat专题 - WebSocket - 案例 - 需求及流程分析

1、WebSocket DEMO 案例需求:通过 websocket 实现一个简易的聊天室功能。

tomcat-70.png

2、WebSocket DEMO 案例流程

1)登录聊天室

2)登录后,进入聊天界面,进行聊天。

3)用户1 聊天界面,用户2 聊天界面。

4)好友列表、单独聊天模式与广播模式。

   tomcat-71.png

3、WebSocket DEMO 案例 实现流程

tomcat-72.png

4、消息格式

客户端 --> 服务端: {“fromName”:“Deng”,“toName”:“HEIMA”,“content”:“约会呀”}

服务端 --> 客户端:

1)如果 type 为 user,则说明返回的是用户列表

{“data” : “HEIMA, Deng, ITCAST” ,“toName” :“” ,“fromName” :“”,“type” :“user” }

2)如果 type 为 message,则说明返回的是消息内容

{“data” : “你好” ,“toName” : “HE IMA” , " fromName" : “Deng” ,“type” : “message” }

四、Tomcat专题 - WebSocket - 案例 - 准备工作

1、打开 idea 创建 名为 dzs168_chat_room 的 Web Application 项目

--> idea --> File --> New --> Project --> Java Project SDK: ( 1.8(java version "1.8.0_131" ) --> Java EE : 勾选 ( Web Application )--> Next --> Project Name: ( dzs168_chat_room )Project Location: ( ...\dzs168_chat_room\ )	--> Finish	

2、在项目 dzs168_chat_room 中,导入项目依赖( dzs168_chat_room/web/lib/ ),Add as Library…

fastjson-1.2.5.jar
tomcat-websocket.jar
websocket-api.jar

3、在项目 dzs168_chat_room 中,导入静态资源文件。

dzs168_chat_room/web/css/
dzs168_chat_room/web/img/
dzs168_chat_room/web/js/
dzs168_chat_room/web/chat.jsp
dzs168_chat_room/web/login.jsp

4、在项目 dzs168_chat_room 中, Web 应用配置欢迎页面为 login.jsp

(project_tomcat\dzs168_chat_room\web\WEB-INF\web.xml)


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list></web-app>
<!-- project_tomcat\dzs168_chat_room\web\WEB-INF\web.xml -->

5、配置 dzs168_chat_room 应用,进行测试。


idea ---> Run/Debug Configurations 
---> 点击 应用 Tomcat 8.5.47
---> Deployment 删除已经存在的应用。---> 点击 + 添加新应用 Artifact... ,选择我们的项目 dzs168_chat_room.war exploded---> Application context: ( / )---> Apply ---> Server---> On'Update'action:  ( Update classes and resources )---> On frame deactivation: ( Update classes and resources )---> Apply 
---> OK

6、运行 tomcat 服务器,自动打开欢迎页面,localhost:8080

在这里插入图片描述

上一节关联链接请点击
利刃出鞘_Tomcat 核心原理解析(十)-- Tomcat 性能调优–2

这篇关于# 利刃出鞘_Tomcat 核心原理解析(十一)-- WebSocket -- 1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130401

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹