java - 是否可以在同一上下文中服务器 websocket 处理程序和普通 servlet?

标签 java servlets websocket servlet-filters spring-websocket

是否可以在同一上下文中为 websocket 处理程序和普通 servlet 提供服务?

示例

http://localhost/appcontext/endpoint  --> serving by normal servlet
ws://localhost/appcontext/endpoint --> serving by websocket handler

我尝试了多种方法,但还是不行。看来 url 映射是由上下文路径过滤的,而不是由“http”或“ws”等协议(protocol)过滤的。也许我发现的东西是错误的。我试图使用 spring 和 java 来实现这一点。

最佳答案

简短回答:

不,您不能使用 servlet 或 websocket 提供的相同路径。每个对 http://localhost/appcontext/endpoint 的 http 请求都应该有特定的行为

长答案:

这个答案超出了 Java 范围,因为它主要依赖 RFC 6455 ,又名 websocket 圣经。原因在于握手过程。

Websocket URI

在 RFC 6455 第 3 节中,websocket URI 定义如下:

ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]

wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]

将 URI 详细信息放在一边,人们实际上可能认为可以仅使用 HTTP 协议(protocol)访问 HTTP 对应部分。

握手:客户端

提醒:websocket 是一个双向协议(protocol)。因此,客户端是初始化连接的实体。然而,一旦建立连接,客户端和服务器都可以发送消息或关闭通信。但是服务器和客户端的概念是要知道谁是谁

客户端初始化握手:“嘿服务器!我想建立webosocket通信”。然而,握手是通过 http 开始的。 RFC 6455 第 17 页(第 4.1 节):

  1. The handshake MUST be a valid HTTP request as specified by [RFC2616].

  2. The method of the request MUST be GET, and the HTTP version MUST be at least 1.1.

    For example, if the WebSocket URI is "ws://example.com/chat", the first line sent should be "GET /chat HTTP/1.1".

  3. The "Request-URI" part of the request MUST match the /resource name/ defined in Section 3 (a relative URI) or be an absolute http/https URI that, when parsed, has a /resource name/, /host/, and /port/ that match the corresponding ws/wss URI.

每个 websocket 通信初始化的背后都隐藏着相同路径的 HTTP 请求。回到你的例子:

  1. 客户端询问ws://localhost/appcontext/endpoint
  2. 它实际上要求 http://localhost/appcontext/endpoint 提供升级请求和 RFC 6455 定义的相应 header
  3. 服务器应答,并且只有在握手之后,通信才会从 http(s) 切换到 ws(s)

握手:服务器端

但是,如果您想作弊并说“我假装我不知道这是一个 websocket URI,并且我想访问此 URL 后面的 HTTP 资源”,该怎么办?在服务器端,您的应用程序已将 URI 匹配的路径 http://localhost/appcontext/endpoint 注册为“我正在此处等待 Websocket 连接”,类似于 Web 服务路径匹配过程。 RFC 6455 第 4.2.1 节中:

The client’s opening handshake consists of the following parts. If the server, while reading the handshake, finds that the client did not send a handshake that matches the description below (note that as per [RFC2616], the order of the header fields is not important), including but not limited to any violations of the ABNF grammar specified for the components of the handshake, the server MUST stop processing the client’s handshake and return an HTTP response with an appropriate error code (such as 400 Bad Request).

  1. An HTTP/1.1 or higher GET request, including a "Request-URI" [RFC2616] that should be interpreted as a /resource name/ defined in Section 3 (or an absolute HTTP/HTTPS URI containing the /resource name/).

  2. A |Host| header field containing the server’s authority.

  3. An |Upgrade| header field containing the value "websocket", treated as an ASCII case-insensitive value.

由于 http://localhost/appcontext/endpoint 已注册用于 Websocket 握手,因此基本 HTTP 请求不包含 Upgrade header ,因此会被服务器拒绝.

编辑

在写这个答案时,我尝试过:

  1. 端点:appcontext/端点
  2. 页面:appcontext/endpoint/index.xhtml
  3. 欢迎文件:index.xhtml:因此appcontext/endpoint重定向到index.xhtml

正如预期的那样,我的 websocket 连接失败。如果我将页面路径从 endpoint/index.xhtml 更改为 endpoint2/index.xhtml,Websocket 将恢复正常。

但是,我刚刚发现 http://demos.kaazing.com/echo/使用相同的 URL 进行 websocket 连接,但我找不到原因 >_<

关于java - 是否可以在同一上下文中服务器 websocket 处理程序和普通 servlet?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48006498/

相关文章:

java - 在 Java 中模拟 ADT

java - 地址已被使用 : JVM_Bind java

java - 如何从eclipse调用servlet中的destroy()?

javascript - 如何在javascript中读取json响应

html - 使用 Node.js 调用 .send(data) 时在 HTML5 websocket 上接收 "Error: InvalidStateError: DOM Exception 11"

java - 如何显示从组合框java中选择的项目?

java - 在 Java 包上使用 "ls"命令时出现不支持的方案错误

java - 将 Jetty 与 JAX-RS-Jersey 集成

python - Redis 发布 - 'set' 的参数数量错误

node.js - 是否可以在不使用socket.io的情况下在 Node 中制作聊天应用程序