【问题标题】:How to handle different (url) websocket connections in netty如何在netty中处理不同的(url)websocket连接
【发布时间】:2022-04-06 16:04:21
【问题描述】:

netty 中的 Websocket 示例(示例)有一个 http 请求处理程序:

  1. (一开始)握手

  2. (then) 处理不同类型的 WebSocket 帧,最终处理“TextWebSocketFrame”。

本例中只有一个 url 用于 websocket 连接。

问题是,当基于TextWebSocketFrame 的实际 websocket 通信开始时,没有直接的方法可以从 TextWebSocketFrames 本身确定 websocket url(如果我错了,请纠正我)。

那么,netty 中如何处理不同的(url)websocket 连接?

一种解决方案可以是在握手过程中注册通道及其“websocket 连接 url”。

另一种是只有一个 websocket 连接 url,并通过向 websocket 消息 (TextWebSocketFrames) 添加额外信息来解析不同的上下文。

我不觉得这些解决方案很优雅,有什么想法吗?

【问题讨论】:

标签: websocket netty


【解决方案1】:

据我了解,当您执行 Web 套接字握手时,它是针对特定 URL。这是在网络套接字标准中指定的。见RFC 6455。因此,TextWebSocketFrame 中没有 URL 信息,因为假设帧将被发送到套接字绑定的 URL。

要处理不同的 URL,您必须:

  1. 为每个 URL 设置不同的管道并绑定到不同的 IP 和/或端口,或者
  2. 如您所说,自定义握手并将 URL 与频道一起存储。

就我个人而言,我刚刚在 TextWebSocketFrame 中使用了 JSON。在我的 JSON 中,我有一个说明预期操作的字段。该字段用于路由到适当的消息处理程序。

我认为这取决于设计决策。 WebSockets 旨在用于请求消息可以有 0、1 或 > 1 个响应的长期连接。这与 REST 样式的 1 请求和 1 响应模型形成鲜明对比。

希望这会有所帮助。

【讨论】:

  • 感谢您的回答和您在 netty 中的 RFC 6455 实施。我希望你们尽快完成 netty 3.3 和 4.0。
  • 没问题。它完成了 Web 套接字的编码和(高速公路)测试。只是等待发布。
【解决方案2】:

“如何在netty中处理不同的(url)websocket连接”这个问题没有意义,我想作者的意思是问“如何在单个端口上提供多个不同的websocket路径:主机”。

这个问题是有效的,因为 HTTP 协议、(至少 1.1 版)WebSockets 和 Web 浏览器都支持这种情况:

  • 客户端连接到服务器,两者开始交换 HTTP 请求/响应对。
  • 客户端发送HTTP请求升级到WebSocket,服务器接受它,现在客户端和服务器之间建立了一个WebSocket。
  • 原始 HTTP 连接保持打开状态,因此客户端和服务器可以继续与 WebSocket 并行交换 HTTP 请求/响应对。 (鉴于此,“升级”一词用词不当,因为连接根本没有升级;而是为 WebSocket 建立了一个新连接。)
  • 由于 HTTP 连接仍然可用,客户端可以发送另一个 HTTP 升级请求,从而创建另一个 WebSocket。在客户端,它看起来像这样:
    socket1 = new WebSocket( "https://acme.com:8443/alpha" );
    socket2 = new WebSocket( "https://acme.com:8443/bravo" );

但是,你不能这样,因为 Netty 的所有壮丽荣耀和可怕的复杂性并不完全支持这一点,即使在提出问题 10 年后的现在也是如此。

那是因为:

  • 只有一个ServerBootstrap 可以绑定到给定主机上的给定端口。
    (这就是套接字层的工作原理。)
  • ServerBootstrap 只能有一个“子处理程序”。
    (如果您调用两次,ServerBootstrap.childHandler() 会静默报错,但只有最后一次调用生效。)
  • ChannelPipeline 只能有一个 WebSocketServerProtocolHandler
    (只有您添加的第一个 WebSocketServerProtocolHandler 有效,如果您添加更多,Netty 会默默地无法发出错误。)
  • WebSocketServerProtocolHandler 接受一个且仅一个 webSocketPath。

所以,你有它,一个 port:host 只能有一个 webSocketPath,这是 Netty 的限制。

也许可以通过重写WebSocketServerProtocolHandler 来克服这个限制,但是#aintNoBodyGotNoTimeFoDat。

幸运的是,Netty 确实支持另一个特性,这使得实现类似的事情成为可能。 WebSocketServerProtocolHandler 的构造函数支持文档不完整且名称不正确的 checkStartsWith 参数,如果设置为 true,将导致处理程序不仅在给定的 webSocketPath 上,而且对于以给定开头的任何 webSocket 路径都支持 websocket 协商请求webSocketpath 并以“?”继续或“/”后跟其他内容。因此,客户端上的代码将如下所示:

    socket1 = new WebSocket( "https://acme.com:8443/allWebSocketsHere/alpha" );
    socket2 = new WebSocket( "https://acme.com:8443/allWebSocketsHere/bravo" );

如果您决定构建您的 netty 服务器来处理此问题,您将面临的下一个问题是如何获取“/allWebSocketsHere/alpha”和“allWebSocketsHere/bravo”部分。幸运的是,其他人已经发现了这一点,请参阅“Netty:如何在 websocket 中使用查询字符串?” https://stackoverflow.com/a/47897963/773113

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-16
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多