【发布时间】:2016-04-14 19:49:00
【问题描述】:
我使用的是 Netty 5.0。
我有一个互补的客户端引导程序,我从 netty github 获取了 SecureChatClient.java 示例。
Wenn 我从客户端引导程序向服务器发送消息,它工作得很好。当我尝试从服务器引导程序向客户端发送消息时(首先通过客户端成功启动连接/通道后),我得到一个java.lang.UnsupportedOperationException,没有任何进一步的信息。从服务器向客户端发送消息是通过上面的代码完成的。
serverbootstrap 是否只用于接收?
serverbootstrap 是否不意味着能够将消息写回客户端,如上所示?我的意思是,消息可以从套接字向上通过 ChannelHandlers 进入 ChannelPipeline,但只有 ChannelHandlers 应该将响应写回 ChannelPipeline 并输出套接字。因此,在 ServerBootstrap 中,用户并不意味着能够从管道外部沿 ChannelPipeline 发送消息。 (希望这是有道理的)
或者我只是错过了什么?
我的代码如下:
// Ports.
int serverPort = 8080;
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("MyMessageHandler", new MyMessageHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(serverPort).sync();
Channel ch = f.channel();
System.out.println("Server: Running!");
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
String line = in.readLine();
if (line == null) break;
ByteBuf getOut = buffer(64);
getOut.writeBytes(line.getBytes());
// Sends the received line to the server.
lastWriteFuture = ch.writeAndFlush(getOut);
lastWriteFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture cf) throws Exception {
if(cf.isSuccess()) {
System.out.println("CFListener: SUCCESS! YEAH! HELL! YEAH!");
} else {
System.out.println("CFListener: failure! FAILure! FAILURE!");
System.out.println(cf.cause());
}
}
});
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} catch (InterruptedException | UnsupportedOperationException e) {
e.printStackTrace();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
我开始使用以下示例:https://github.com/netty/netty/tree/4.1/example/src/main/java/io/netty/example/securechat
我的问题是调用ch.writeAndFlush时出现以下异常:
java.lang.UnsupportedOperationException
at io.netty.channel.socket.nio.NioServerSocketChannel.filterOutboundMessage(NioServerSocketChannel.java:184)
at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:784)
at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1278)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeWriteNow(ChannelHandlerInvokerUtil.java:158)
at io.netty.channel.DefaultChannelHandlerInvoker$WriteTask.run(DefaultChannelHandlerInvoker.java:440)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:328)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
at io.netty.util.internal.chmv8.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1412)
at io.netty.util.internal.chmv8.ForkJoinTask.doExec(ForkJoinTask.java:280)
at io.netty.util.internal.chmv8.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:877)
at io.netty.util.internal.chmv8.ForkJoinPool.scan(ForkJoinPool.java:1706)
at io.netty.util.internal.chmv8.ForkJoinPool.runWorker(ForkJoinPool.java:1661)
at io.netty.util.internal.chmv8.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:126)
【问题讨论】:
-
响应您的新
ChannelGroupException错误:您可以将 f.cause() 转换为ChannelGroupException,然后打印其iterator()中的每个值 -
我把整件事都放到了我的问题中。我希望我做的迭代器是对的。我愿意改进或更正。
-
@Ferrybig 由于您的调试技巧解决了这个问题。太感谢了!把答案放在里面有更多的细节。如果有办法给予人们信任,请告诉我。想以某种方式给你点赞。
-
我不确定你是如何解决后半部分的,但在stackoverflow,我们通常在一个问题中只保留一个问题,所以我们可以有一个可以接受的答案,目前你的问题是基于 2 个单独的部分,其中第一部分是我帮助您调试的原始问题,而后一个问题是您发布的答案,我认为最好删除第二部分和您的“一半”答案,然后将我的标记为已接受,因为它解决了您最初的问题,并阻止人们投票以“过于宽泛”来结束您的问题
-
好吧,我明白你的意思了。将进行更改!