Netty ChannelRead 方法
Posted
技术标签:
【中文标题】Netty ChannelRead 方法【英文标题】:Netty ChannelRead method 【发布时间】:2014-12-20 07:58:08 【问题描述】:我是使用 Netty 框架的新手。遇到一个问题,我用Netty写ServerSocket。 服务器的目标是从硬件接收消息。硬件每次发送一个字节。服务器和硬件有一个协议——每条消息都以“#”开头,以“*”结尾。
@Sharable
class ServerHandler extends ChannelInboundHandlerAdapter
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
BytBuf in = (ByteBuf) msg;
CharBuffer charBuffer = CharBuffer.allocate(100);
String recedata ;
byte tmp;
try
while (in.isReadable())
tmp = in.readByte();
if (tmp != 42)
charBuffer.append((char) tmp);
// System.out.println(String.valueOf(charBuffer.array()));
else //means receive a byte '*'
charBuffer.append('*');
count = 0;
recData = String.valueOf(charBuffer.array());
logger.debug("receive message is " + recData);
catch(Exception e)
e.printStackTrace();
但是,出现了问题。当硬件第一次发送#abcd
时,服务器将存储#abcd
然后硬件可能会发送efg*
。由于Netty是异步的和事件驱动的,方法ChannelRead()
会从头到尾运行。所以会打印efg*
,而不是#abcdefg*
我想了很多。最后,我有一个想法。我使用AttribueKey
就像ThreadLocal
绑定一个数组以存储所有接收到的字节与通道。然后我从数组中得到#.....*
。但数组会很大。这不是一个好方法。
你有更好的方法来解决我的问题吗?谢谢你的帮助
【问题讨论】:
【参考方案1】:查看 Netty 用户指南 - 处理基于流的传输。消息可能会变得支离破碎 - 因此在您的情况下,它可能会收到“#abcd”后跟“efg*”。由于您每次都分配一个 CharBuffer,因此原始 CharBuffer 包含“#abcd”。在第二个方法调用中,CharBuffer 包含“efg*”。
解决方案是使用 ByteToMessageDecoder。 decode() 将被重复调用(由 Netty 框架),直到 ByteBuf 为空(即,您的解码代码清空它)。因此,您可以在 decode() 中执行的操作是不断返回,直到“in”ByteBuf 包含 * 字符。完成后,将 ByteBuf 的内容写入“out”列表,从开头的 # 到 *. * 之后的任何剩余字节都将留在 ByteBuf 中,并且该过程将继续。
【讨论】:
这对我很有帮助。我用你的方法,但是解码器不能是@sharable
,那么在客户端很多的情况下如何使用服务器
服务器为每个客户端连接创建一个通道。您需要为每个通道创建一个新的处理程序实例(或多个实例),否则同一处理程序将用于多个线程,在这种情况下,处理程序需要是线程安全的 - 这需要同步和 @Shareable(如果可以避免,则不推荐)开销和增加的复杂性和潜在的锁争用问题)。
感谢您的帮助!现在,我更了解 Netty
太好了,如果您认为已回答,介意将问题标记为已回答吗?以上是关于Netty ChannelRead 方法的主要内容,如果未能解决你的问题,请参考以下文章
Netty中为啥执行channelReadComplete但是不执行channelRead