Netty 网状通道读取法
我是使用Netty框架的新手。我遇到一个问题,我用Netty来写ServerSocket。 服务器的目标是接收来自硬件的消息。硬件每次发送一个字节。服务器和硬件有一个协议——每条消息都以“#”开头,以“*”结尾Netty 网状通道读取法,netty,serversocket,channel,Netty,Serversocket,Channel,我是使用Netty框架的新手。我遇到一个问题,我用Netty来写ServerSocket。 服务器的目标是接收来自硬件的消息。硬件每次发送一个字节。服务器和硬件有一个协议——每条消息都以“#”开头,以“*”结尾 @Sharable class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object m
@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();
}
}
}
但是,出现了一个问题。当硬件首次发送时,服务器将存储
然后,硬件可能会发送efg*
。由于网络是异步和事件驱动的,因此方法ChannelRead()
将自始至终运行。因此打印efg*
,而不是#abcdefg*
我想了很多。最后,我有一个想法。我使用AttribueKey
,它类似于ThreadLocal
,绑定一个数组来存储通道中所有接收到的字节。然后我从数组中获取#…*
。但是阵列将非常大。这不是一个好方法。
你有更好的方法解决我的问题吗?感谢您的帮助查看Netty用户指南-处理基于流的传输。该消息可能会变得支离破碎,因此在您的情况下,它可能会收到“#abcd”后跟“efg*”。由于每次都分配一个CharBuffer,因此原始CharBuffer包含“#abcd”。在第二个方法调用中,CharBuffer包含“efg*”
解决方案是使用ByteToMessageDecoder。decode()将被(Netty framework)反复调用,直到in ByteBuf为空(即,您的解码代码将其清空)。因此,在decode()中可以执行的操作是不断返回,直到“in”ByteBuf包含*char。完成后,将ByteBuf的内容从开始处#到*写入“输出”列表。*之后的所有剩余字节都将保留在ByteBuf中,该过程将继续。这对我非常有帮助。我使用你的方法。但是解码器不能是
@sharable
,所以当有很多客户端时,我如何使用服务器?服务器为每个客户端连接创建一个通道。您需要为每个通道创建一个新的处理程序实例(或多个实例),否则同一个处理程序将用于多个线程,在这种情况下,处理程序需要是线程安全的-这需要同步和@Shareable(如果由于开销和增加的复杂性以及潜在的锁争用问题可以避免,则不建议使用).谢谢你的帮助!现在,我知道内蒂·莫雷特了,如果你觉得这个问题已经被回答了,你介意把它标记为已回答吗?