java – Netty获取一个exceptionCaught()事件被触发,它到达TextWebsocketEncoder管道的尾部
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – Netty获取一个exceptionCaught()事件被触发,它到达TextWebsocketEncoder管道的尾部,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8555字,纯文字阅读大概需要13分钟。
内容图文
我尝试进行简单的Web套接字解码然后编码,但是当它传递TextWebsocketDecoder处理程序时我得到了这个异常:
io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
WARNING: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101)
at io.netty.buffer.DefaultByteBufHolder.release(DefaultByteBufHolder.java:73)
at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:59)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:112)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
at io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler$1.channelRead(WebSocketServerProtocolHandler.java:147)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:276)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:263)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:745)
我所拥有的是简单的初始化程序,它直到TextWebsocketEncoder才能找到它:
public class ServerInitializer extends ChannelInitializer<Channel> {
private final ChannelGroup group;
public GameServerInitializer(ChannelGroup group) {
this.group = group;
}
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(64 * 1024));
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpRequestHandler("/ws"));
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
pipeline.addLast(new TextWebSocketFrameHandler(group));
pipeline.addLast("textWebsocketDecoder",new TextWebsocketDecoder());
pipeline.addLast("textWebsocketEncoder",new TextWebsocketEncoder());
}
}
TextWebSocketFrameHandler
public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
private final ChannelGroup group;
public TextWebSocketFrameHandler(ChannelGroup group) {
this.group = group;
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) {
ctx.pipeline().remove(HttpRequestHandler.class);
group.writeAndFlush(new TextWebSocketFrame("Client " + ctx.channel() + " joined"));
group.add(ctx.channel());
} else {
super.userEventTriggered(ctx, evt);
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
ctx.fireChannelRead(msg);
//group.writeAndFlush(msg.retain());
}
}
这是TextWebsocketDecoder和TextWebsocketEncoder:
TextWebsocketDecoder:
public class TextWebsocketDecoder extends MessageToMessageDecoder<TextWebSocketFrame>
{
@Override
protected void decode(ChannelHandlerContext ctx, TextWebSocketFrame frame, List<Object> out) throws Exception
{
String json = frame.text();
JSONObject jsonObject = new JSONObject(json);
int type = jsonObject.getInt("type");
JSONArray msgJsonArray = jsonObject.getJSONArray("msg");
String user = msgJsonArray.getString(0);
String pass = msgJsonArray.getString(1);
String connectionkey = msgJsonArray.getString(2);
int timestamp = jsonObject.getInt("timestamp");
JSONObject responseJson = new JSONObject();
responseJson.put("type",Config.LOGIN_SUCCESS);
responseJson.put("connectionkey",connectionkey);
out.add(responseJson); // After This im getting the exception !!!
}
}
TextWebsocketEncoder
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
public class TextWebsocketEncoder extends MessageToMessageEncoder<JSONObject>
{
@Override
protected void encode(ChannelHandlerContext arg0, JSONObject arg1, List<Object> out) throws Exception {
String json = arg1.toString();
out.add(new TextWebSocketFrame(json));
}
}
解决方法:
例外
在TextWebSocketFrameHandler中,您正在调用ctx.fireChannelRead(msg);,这会将消息传递到1链,但MessageToMessageDecoder不准备处理此问题.为了解释这个问题,我需要解释MessageToMessageDecoder的工作原理.
MessageToMessageDecoder通过捕获来自上游的每条消息并将它们传递给您的自定义代码,您的自定义代码处理工作,以及mtmd处理您传入的资源的关闭来工作.
由于您将引用传递给另一方,因此您实际上多次关闭WebSocketFrame,从而导致错误. MessageToMessageDecoder甚至在javadoc中警告你.
要解决这个问题,我们按照手册中的说明进行操作,并阅读以下内容:
@Override
public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
msg.retain(); // ferrybig: fixed bug https://stackoverflow.com/q/34634750/1542723
ctx.fireChannelRead(msg);
//group.writeAndFlush(msg.retain());
}
不回送问题
在您的评论中,您声明代码不会发回任何内容.这是预期的,因为您的管道只消耗数据并将其传递给链.要解决这个问题,需要在管道上进行一些修改.
>我们需要交换json-webframe解码器和编码器的顺序:
pipeline.addLast("textWebsocketDecoder",new TextWebsocketEncoder());
pipeline.addLast("textWebsocketEncoder",new TextWebsocketDecoder());
这是因为您的解码器正在生成将返回↑处理程序链的输出,如果解码器高于此值,则编码器将看不到此输出. (在netty命名后,您的解码器不应被称为解码器)
>我们需要更改您的解码器,将生成的数据实际发送回↑链而不是↓进入不存在的空白.
为了进行这些更改,我们将让TextWebSocketDecoder扩展ChannelInboundHandlerAdapter而不是MessageToMessageDecoder< TextWebSocketFrame>因为我们正在处理消息而不是将它们传递给其他处理程序.
我们正在将decode方法的签名更改为channelRead(ChannelHandlerContext ctx,Object msg),并添加一些样板代码:
public void channelRead(ChannelHandlerContext ctx, Object msg) /* throws Exception */
TextWebSocketFrame frame = (TextWebSocketFrame) msg;
try {
/* Remaining code, follow the steps further of see end result */
} finally {
frame.release();
}
}
>我们调整代码以将结果传递给管道而不是向下传递:
public void channelRead(ChannelHandlerContext ctx, Object msg) /* throws Exception */
TextWebSocketFrame frame = (TextWebSocketFrame) msg;
try {
String json = frame.text();
JSONObject jsonObject = new JSONObject(json);
int type = jsonObject.getInt("type");
JSONArray msgJsonArray = jsonObject.getJSONArray("msg");
String user = msgJsonArray.getString(0);
String pass = msgJsonArray.getString(1);
String connectionkey = msgJsonArray.getString(2);
int timestamp = jsonObject.getInt("timestamp");
JSONObject responseJson = new JSONObject();
responseJson.put("type",Config.LOGIN_SUCCESS);
responseJson.put("connectionkey",connectionkey);
ctx.writeAndFlush(responseJson)
} finally {
frame.release();
}
}
请注意,您可能想要从异常中删除我们以前的代码,但是这样做会在netty的异步性质下运行时触发未定义的行为.
内容总结
以上是互联网集市为您收集整理的java – Netty获取一个exceptionCaught()事件被触发,它到达TextWebsocketEncoder管道的尾部全部内容,希望文章能够帮你解决java – Netty获取一个exceptionCaught()事件被触发,它到达TextWebsocketEncoder管道的尾部所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。