netty中的Websocket示例(示例)有一个http请求处理程序,它是:
-
进行握手(最初)
-
(然后)处理不同类型的WebSocket帧,最终是"TextWebSocketFrame"。
在这个例子中,websocket连接只有一个url。
问题是,当基于TextWebSocketFrame
的实际websocket通信开始时,没有直接的方法从TextWebSocketFrame本身确定websocket url(如果我错了,请纠正我)。
那么,如何在netty中处理不同的(url)websocket连接呢?
一种解决方案可以是在握手过程中注册通道及其"websocket连接URL"。
另一种是只有一个websocket连接url,并通过向websocket消息(TextWebSocketFrame)添加额外信息来解析不同的上下文。
我觉得这些解决方案并不优雅,有什么想法吗?
我的理解是,当您执行web套接字握手时,它指向特定的URL。这是在web套接字标准中指定的。参见RFC 6455。因此,TextWebSocketFrame中没有URL信息,因为假设帧将被发送到套接字绑定的URL。
要处理不同的URL,您必须:
- 为每个URL设置不同的管道并绑定到不同的IP和/或端口,或者
- 正如你所说,定制握手并将URL与频道一起存储
就我个人而言,我刚刚在TextWebSocketFrame中使用了JSON。在我的JSON中,我有一个字段来说明预期的操作。此字段用于路由到适当的消息处理程序。
我认为这可以归结为一个设计决定。WebSocket用于请求消息可以具有0、1或>1个回复。这对比了REST风格的1请求和1响应模型。
希望这能有所帮助。
问题"如何在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
可以绑定到给定端口
(套接字层就是这样工作的。) - 一个CCD_ 3只能有一个";子处理程序"
(如果ServerBootstrap.childHandler()
调用两次,它将不会自动报告错误,但只有最后一次调用才会生效。) ChannelPipeline
只能有一个WebSocketServerProtocolHandler
(只有添加的第一个WebSocketServerProtocolHandler
有效,如果添加更多,Netty将不会发出错误。)WebSocketServerProtocolHandler
只接受一个webSocketPath
因此,端口:主机只能有一个webSocketPath,这是Netty的限制。
也许可以通过重写WebSocketServerProtocolHandler
来克服这个限制,但是#aintNoBodyGotNoTimeFoDat。
幸运的是,Netty确实支持另一个功能,这使得实现类似的功能成为可能。WebSocketServerProtocolHandler
的构造函数支持一个文档不完整、名称不正确的checkStartsWith
参数,如果该参数设置为true,将导致处理程序不仅在给定的webSocketPath上,而且在以给定的webSocketPath开始并以"?"继续的任何websocket路径上接受websocket协商请求或者一个"/"后面跟着其他东西。因此,客户端上的代码看起来是这样的:
socket1 = new WebSocket( "https://acme.com:8443/allWebSocketsHere/alpha" );
socket2 = new WebSocket( "https://acme.com:8443/allWebSocketsHere/bravo" );
如果你决定构建你的netty服务器来处理这个问题,你将面临的下一个问题是如何获得"/allWebSocketHere/alpha";以及";allWebSocketsHere/bravo";零件。幸运的是,其他人已经明白了这一点;Netty:如何在websocket中使用查询字符串"https://stackoverflow.com/a/47897963/773113