Netty:正确关闭WebSockets

5
我该如何正确地从服务器端关闭WebSocket通道/连接?如果我使用ctx.getChannel().close(),则浏览器(Firefox 9)中的onerror会被抛出:The connection to ws://localhost:8080/websocket was interrupted while the page was loading。我还尝试在WebSocketServerHandler中的channelClosed方法中发送一个CloseWebSocketFrame
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
        throws Exception {
    CloseWebSocketFrame close = new CloseWebSocketFrame();
    ctx.getChannel().write(close);
}

这会抛出一个ClosedChannelException异常(可能与此问题有关?)。

4个回答

6
你需要做这个事情:
ch.write(new CloseWebSocketFrame());

然后服务器将关闭连接。如果连接没有及时关闭,您可以调用ch.close()


WebSocket连接建立后,我的管道看起来像这样:[wsdecoder,wsencoder,webSocketHandler,myDecoder,myEncoder,app]。因此,WebSocketHandler将数据转发到解码器,直到它到达应用程序。问题是,app不知道它的使用方式。因此,它根本不知道管道中是否有WebSocketHandler。这样,app也可以在其他非WebSocket连接的管道中使用。即使我将CloseWebSocketFrame写入channel中的app,它也会被编码,直到它到达WebSocketServerHandler - Dennis
我刚刚测试了一些东西:在管道的任何层中进行ch.write(...),它是否会通过整个管道(从最后一个处理程序到第一个处理程序)?我原以为它只会回到我们执行ch.write(...)的那一层。 - Dennis
2
因为我引入了上述行为,所以我创建了一个名为ChannelClosing的类。我在通道上写入该类的实例:ch.write(new ChannelClosing());。如果我在解码器中(该解码器将我的应用程序数据转换为WebSockets)发现了它,我会切换到CloseWebSocketFrame。这有效运行。 - Dennis

2
如何?
ctx.getChannel().write(new CloseWebSocketFrame()).addListener(ChannelFutureListener.CLOSE);

这应该发送CloseWebSocketFrame,然后在此之后关闭通道。


0
你使用的是哪个版本?
你尝试过做这个吗:
ctx.getChannel().write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);

?


不行。仍然是“ClosedChannelException”。CloseWebSocketFrame的构造函数包含ChannelBuffers.EMPTY_BUFFER。我想我需要使用CloseWebSocketFrame - Dennis
RFC 6455(http://tools.ietf.org/html/rfc6455#section-7.4.1)定义了:*1001表示端点“正在离开”,例如服务器关闭或浏览器导航离开页面。* 这就是我想要使用的。 - Dennis
版本:我正在使用我的分支(https://github.com/boldt/netty)。由于Netty已经模块化,我无法再编译它了。 - Dennis
对于像我一样通过谷歌来到这里的其他人:我正在尝试使用HTTP通道,对我来说这是完美的解决方案。 - user85155

0

我遇到了同样的问题(从服务器端关闭WebSocket通道/连接),解决方法如下:

ctx.getChannel().writeAndFlush(new CloseWebSocketFrame(1000, "Server closed connection."));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接