千家信息网

WebSocket原理及Tomcat的实现是怎样的

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,WebSocket原理及Tomcat的实现是怎样的 ,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。现如今,许多场景下需要
千家信息网最后更新 2025年02月02日WebSocket原理及Tomcat的实现是怎样的

WebSocket原理及Tomcat的实现是怎样的 ,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

现如今,许多场景下需要实现从服务端到客户端的主动推送消息。而对于传统的HTTP,我们都了解,其必须是要通过主动的请求,每个Request对应一个Response,此时要实现服务端推,必须要有一个主动的请求。

为此,人们想出了ajax长轮询,长连接等一系列方式,但对比长轮询的不断无效的请求,都不如使用我们今天提到的更方便且不消耗资源实现。

对比HTTP请求,比较明显的你会感觉到,无论是异步还是同步请求,对于HTTP,在开发者工具中你都能观察到应用是新发了一个请求到服务器,之后根据返回的信息进行处理展示的。

而WebSocket,则在第一次握手建立连接之后,后续的收发消息,都不再重新建立连接,也就是你观察不到它后续的请求了。

这也是HTTP与WebSocket的区别。

而在Tomcat内部,我们来看Websocket是如何生效及工作的。

首先,来看WebSocket是如何初始化的。

无论哪种类型的请求,都会在ApplicationFilterChain中进行处理,根据是否配置Filter来决定整个处理的流向。(前面曾介绍过Filter的工作原理及请求流程:责任链模式及Filter的工作原理)。而无论哪个应用,其实Tomcat内部都会为其默认添加这样一个Filter:

WsFilter

这个Filter就是用来处理WebSocket的,但又不全是,因为它的filter-mapping是

/*

FilterRegistration.Dynamic fr = servletContext.addFilter(

"Tomcat WebSocket (JSR356) Filter", new WsFilter());

fr.setAsyncSupported(true);

EnumSet types = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);

fr.addMappingForUrlPatterns(types, true, "/*");

上面的代码即是使用Servlet3.0新增加的动态声明Filter的实现方式,把WsFilter这个动态增加到应用的filter链中。

而这个Filter中,也是在入口处判断,只有WebSocket的请求才处理,其它的就跳过了


// This filter only needs to handle WebSocket upgrade requests

if (!sc.areEndpointsRegistered() ||

!UpgradeUtil.isWebSocketUpgradeRequest(request, response)) {

chain.doFilter(request, response);

return;

}

添加Filter这一行为,是在应用启动的时候执行的,调用栈如下:

at org.apache.catalina.core.StandardContext.addFilterMap(StandardContext.java:2836)

at org.apache.catalina.core.ApplicationFilterRegistration.addMappingForUrlPatterns(ApplicationFilterRegistration.java:104)

at org.apache.tomcat.websocket.server.WsServerContainer.(WsServerContainer.java:141)

at org.apache.tomcat.websocket.server.WsSci.init(WsSci.java:131)

at org.apache.tomcat.websocket.server.WsSci.onStartup(WsSci.java:47)

at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5151)

请求连接建立

在数据发送之前,需要先建立连接。而WebSocket本质上仍然是TCP连接,虽然看起来是通过HTTP,只是因为其初次的握手是需要通过HTTP来建立。

我们以Tomcat自带的websocket样例中的echo例子来说明WebSocket的使用方式以及其在Tomcat内部的实现形式。

echo例子位于:

TOMCAT_HOME\webapps\examples\websocket

java代码位于:

TOMCAT_HOME\webapps\examples\WEB-INF\classes\websocket\echo

代码中,对于connect和echo message的实现如下:

function connect() {

var target = document.getElementById('target').value;

if (target == '') {

alert('Please select server side connection implementation.');

return;

}

if ('WebSocket' in window) {

ws = new WebSocket(target);

} else if ('MozWebSocket' in window) {

ws = new MozWebSocket(target);

} else {

alert('WebSocket is not supported by this browser.');

return;

}

ws.onopen = function () {

setConnected(true);

log('Info: WebSocket connection opened.');

};

ws.onmessage = function (event) {

log('Received: ' + event.data);

};

ws.onclose = function (event) {

setConnected(false);

log('Info: WebSocket connection closed, Code: ' + event.code + (event.reason == "" ? "" : ", Reason: " + event.reason));

};

}

我们看到,整个websocket对象会处理三个事件:

  • connect

  • message

  • close

而信息的发送,是直接使用websocket的send方法。

在初次连接握手时,通过开发者工具,我们可以观察到:


是通过Upgrade来进行协议的切换,同时连接到WebSocket 的Server上去的。

而此时的Upgrade就是通过我们前面提到的Filter来进行的。

在Filter中,通过UgradeUtil的doUpgrade方法进行后续关于WebSocket规范的调用实现。

而对于WebSocket Server 的支持,我们通过Echo的例子可以看到,可以直接使用Endpoint的类来进行,也可以通过注解的等式进行。

例如下面的代码就是通过注解的形式,声明了一个Websocket的Endpoint

@ServerEndpoint("/websocket/echoAnnotation")
public class EchoAnnotation {
@OnMessage
public void echoTextMessage(Session session, String msg, boolean last) {
try {
if (session.isOpen()) {
session.getBasicRemote().sendText(msg, last);
}
} catch (IOException e) {
}
}

根据注解,Tomcat内部会生成一个PojoServer,并使用反射调用当前标注有@OnMessage的方法。

而请求的分发,我们在前面介绍Connector的时候,曾简单说过是经过

Endpoint -> Handler -> Protocol

(Tomcat的Connector组件)

对于不同的请求,Protocol中进行不同的转发,

} else if (processor.isAsync() ||
state == SocketState.ASYNC_END) {
state = processor.asyncDispatch(status);
} else if (processor.isComet()) {
state = processor.event(status);
} else if (processor.isUpgrade()) {
state = processor.upgradeDispatch(status);
} else if (status == SocketStatus.OPEN_WRITE) {
// Extra write event likely after async, ignore
state = SocketState.LONG;
}

在建立连接之后,后续再进行的数据发送,通过开发者工具已经观察不到任何的请求了,这也是WebSocket之所以可以实现服务器推送的主要原因。其本质上在建立连接后,已经不再是一个HTTP请求了,而是一个TCP连接。

而且因于WebSocket在HTML5中的规范实现,各个主流浏览器的支持,现在多数的应用服务器也都已经根据规范进行了支持。许多要实现服务器推的场景也可以考虑使用WebSocket来实现。

打开Tomcat的webSocket样例,来体验一下吧!

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

处理 服务 应用 代码 服务器 支持 观察 原理 主动 例子 就是 工具 开发者 方式 方法 注解 工作 开发 不同 信息 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 labview删除数据库 有信号但没有数据库 软件开发收入确认会计准则 服务器响应速度 供电公司网络安全承诺书样本 新三板软件开发公司有哪些 c 软件开发师招聘 pg数据库版本推荐 深圳市指峰网络技术有限公司 网络安全技术防范的目标 数据库中的大整数数据类型 我的世界修真服务器 软件开发工资累吗 电脑模拟器金铲铲服务器进不去 丹东哪个服务器最好 手机软件开发怎么做 上饶政务软件开发价格 网络安全员证咋查询 数据库怎么查询表的大小 网络安全协调科科长是什么级别 数据库进不了系统怎么办 旷野之息最新服务器 辽宁软件开发郑重承诺 服务器密码忘了怎么进入系统 国内低调科技公司互联网公司 甘肃电商软件开发哪家好 青岛微信小程序软件开发平台 华为光网络技术基础视频 卫健委网络安全应急演练宣贯会 武汉西湖服务器汽车充电
0