上一篇介绍了netty的创建,本篇章主要介绍在netty中的handler处理和创建,上篇章里面加入了几个handler,本文介绍这几个handlder。
一、EchoClientHandler 主要处理netty的数据包通过队列的方式,传输给上篇章的网关的写线程
import com.jingan.sdk.core.logger.Logger;
import java.nio.ByteBuffer;
import java.util.concurrent.ConcurrentLinkedQueue;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* 作者 :Karision.Gou
* create by 2022/10/11
*/
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
private ConcurrentLinkedQueue<ByteBuffer> queue;
EchoClientHandler(ConcurrentLinkedQueue<ByteBuffer> queue) {
this.queue = queue;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
//连接成功 发送给读线程 可以进入发送数据了
Logger.d("The netty server connect success");
byte[] bytes = new byte[3];
bytes[0] = 115;
bytes[1] = 1;
bytes[2] = 0;
if (queue != null) {
queue.offer(ByteBuffer.wrap(bytes));
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
putBuffer(in);
}
private void putBuffer(ByteBuf in){
ByteBuffer acquire = NettyByteBufferPool.acquire();
while (acquire.limit() < in.readableBytes()) {
acquire = NettyByteBufferPool.acquire();
}
acquire.position(0);
byte[] bytes = new byte[in.readableBytes()];
in.readBytes(bytes);
in.clear();
acquire.put(bytes, 0, bytes.length);
acquire.flip();
if (queue != null) {
queue.offer(acquire);
}
}
}
二、EchoClientHandlerV2 主要是处理自定义的协议包(本handler处理的是TLV协议模式的),并解析完整的数据包,传递给下一个handler(EchoClientHandler)
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
public class EchoClientHandlerV2 extends ByteToMessageDecoder {
private ConcurrentLinkedQueue<ByteBuffer> queue;
EchoClientHandlerV2(ConcurrentLinkedQueue<ByteBuffer> queue) {
this.queue = queue;
}
private int totalByteLength(ByteBuf msg, int byteBLength) {
int byteLenth = 0;
if (byteBLength > 0) {
switch (byteBLength) {
default:
byteLenth = (msg.getByte(1)&0xff) + 2;
break;
case 2:
byteLenth = ByteBuffer.wrap(new byte[]{msg.getByte(2), msg.getByte(3)}).getChar();
byteLenth = byteLenth + 4;
break;
case 3:
byteLenth = ByteBuffer.wrap(new byte[]{0, msg.getByte(2), msg.getByte(3), msg.getByte(4)}).getInt();
byteLenth = byteLenth + 5;
break;
case 4:
byteLenth = ByteBuffer.wrap(new byte[]{msg.getByte(2), msg.getByte(3), msg.getByte(4), msg.getByte(5)}).getInt();
byteLenth = byteLenth + 6;
break;
}
}else {
byteLenth = (msg.getByte(1)&0xff) + 2;
}
return byteLenth;
}
/**
* 十进制转二进制并计算长度
*
* @param n
* @return
*/
public int binaryToDecimal(int n) {
n = n & 0xff;
String str = "";
while (n != 0) {
str = n % 2 + str;
n = n / 2;
}
if (str.length() >= 8) {
return Integer.parseInt(str.substring(1), 2);
}
return 0;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
int length = 0;
while (in.readerIndex() < in.readableBytes() && in.readableBytes() >= length) {
int byteBLength = binaryToDecimal(in.getByte(1));
length = totalByteLength(in, byteBLength);
if (length>in.readableBytes()){
continue;
}
ByteBuf byteBuf = Unpooled.buffer(length);
in.getBytes(0, byteBuf);
in.skipBytes(length);
in.discardReadBytes();
out.add(byteBuf);
}
}
}