如何让Netty从在不同端口上的不同服务器(“节点”)上提供的Web应用程序提供服务/接受Websocket

时间:2019-02-16 16:16:30

标签: websocket netty

我正在Angular 7 webapp中使用一个websocket。这个想法是让网络应用由“节点”提供-例如在地址

http://localhost:4200/

和websocket在Netty / Java应用提供服务的另一个地址和端口上。

在网络应用程序上,我导航到网络套接字的页面。有一个文本框用于输入websocket的地址和按钮:'Connect'-将我们连接到web-socket服务器。例如,对此地址进行测试可以正常工作:

ws://echo.websocket.org          // works - we get a response
or
ws://echo.websocket.org:80       // works - we get a response

相反,我想让Netty服务器来服务websocket。我启动服务器-在以下地址提供服务:

http://localhost:8081/

,运行正常。 (我可以从单独的浏览器窗口和服务器在此地址和端口上提供的websocket页面进行连接。

但是现在我想从我的Web应用程序在localhost:4200 /上连接到Netty服务器。因此,我将此地址提供给套接字连接;

ws://localhost:8081/

然后单击“连接”。

Netty服务器对此日志做出反应(所有行同时显示):

Feb 16, 2019 7:26:20 AM io.netty.handler.logging.LoggingHandler channelRead
INFO: [id: 0xfd77a1f7, L:/0:0:0:0:0:0:0:0:8081] READ: [id: 0x24ad1bc1, L:/127.0.0.1:8081 - R:/127.0.0.1:51928]
Feb 16, 2019 7:26:20 AM io.netty.handler.logging.LoggingHandler channelReadComplete
INFO: [id: 0xfd77a1f7, L:/0:0:0:0:0:0:0:0:8081] READ COMPLETE
Websocke channel Active:[id: 0x24ad1bc1, L:/127.0.0.1:8081 - R:/127.0.0.1:51928]
Websocke channel Inactive:[id: 0x24ad1bc1, L:/127.0.0.1:8081 ! R:/127.0.0.1:51928]
Websocke channel Unregistered:[id: 0x24ad1bc1, L:/127.0.0.1:8081 ! R:/127.0.0.1:51928]

这可能意味着通信正常,但是Netty不接受并且正在关闭websocket。

这些是我在Netty管道中的处理程序:

    new HttpServerCodec());
    new HttpObjectAggregator(65536));
    new WebSocketServerCompressionHandler());
    new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
              // Next handler serves index.html page
              //   ... extends SimpleChannelInboundHandler<FullHttpRequest>
              //       @Override
              //      protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
    new WebSocketIndexPageHandlerA1(WEBSOCKET_PATH));
              // Next handler handles websocket communication
              //   ... extends SimpleChannelInboundHandler<WebSocketFrame>
              //       @Override
              //      protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
    new WebSocketFrameHandlerA1());

我们如何让Netty接受此websocket请求并将流向下传递到我的最后一个处理程序-Web套接字消息处理程序-WebSocketFrameHandlerA1,以便它可以答复Websocket客户端-无论它们来自何处?

1 个答案:

答案 0 :(得分:0)

这个问题有一个相当简单和合理的答案。我们只需要为Netty的管道机智处理程序配备对应于来自客户端的预期流量(HTTP / Websocket等)。

因此,如果我们尝试使用以下方式连接到Netty:

ws://localhost:8081/

服务器将收到初始HTTP请求-如下所示:

GET / HTTP/1.1
Host: localhost:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://localhost:4200
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: XVXVXS%GDDD+lDfDS==
Connection: keep-alive, Upgrade
Cookie: _ga=GA1.1.1146780314.5634479786
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Connection : keep-alive, Upgrade
Upgrade : websocket

我们必须确保管道中有适当的处理程序,以处理初始HTTP请求,然后升级/切换到websocket处理程序。在这种情况下,初始管道可以像这样简单:

pipeline.addLast("httpServerCodec", new HttpServerCodec());
pipeline.addLast("httpHandler", new HttpServerHandler());

HttpServerHandler中的其他内容包括:

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {

        if (msg instanceof HttpRequest) {

            HttpRequest httpRequest = (HttpRequest) msg;
            HttpHeaders headers = httpRequest.headers();

            if (headers.get(HttpHeaderNames.CONNECTION).toUpperCase().contains("UPGRADE") &&
            headers.get(HttpHeaderNames.UPGRADE).toUpperCase().contains("WEBSOCKET")) {

                // Replace the HTTP handler with a websocket handler
                // in the existing pipeline to handle WebSocket Messages
                ctx.pipeline().replace(this, "websocketHandler", new WebSocketHandler());
                //Do the Handshake to upgrade connection from HTTP to WebSocket protocol
            handleHandshake(ctx, httpRequest);
        }
        ...
      }

在您的websocket处理程序中,插入客户端和服务器之间的数据交换逻辑。