netty实战(一)聊天服务
经典例子,netty聊天服务,用来作为第一个实战来理解netty流程适合不过了。
netty出现是为了方便大家使用NIO来进行编程,特别是socket编程。而很多的socket编程都会有很多的协议,我们此次只是为了体验netty,所以不设置协议,直接裸体读写。
聊天消息结构体
public class MsgData {
String name;
String msg;
String data;
int device;
//省略
}
其实搞什么都无所谓,毕竟目前走通pipeline,msg最重要。
handler
netty中handler可以说是我们编码著需要注意的,对于对称消息来说,无非就解码和编码。所以此处我们使用序列化将对象转化为byte,同理在返回,轻快简介。
关于理论篇可以去看netty理论部分
以下是主要的handler处理部分,使用的是Kryo的序列化。功能就是把消息转化为byte,byte转化为消息。然后把byte写入btyebuff将bytebuff转化为消息。由于消息是相同的类型,我们只用了一套编码器与解码器。
public class MsgDataDecoder extends ReplayingDecoder<MsgData> {
private Kryo kryo = new Kryo();
public static final int HEAD_LENGTH = 4;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() < HEAD_LENGTH) {
//这个HEAD_LENGTH是我们用于表示头长度的字节数。 由于Encoder中我们传的是一个int类型的值,所以这里HEAD_LENGTH的值为4.
return;
}
in.markReaderIndex(); //我们标记一下当前的readIndex的位置
int dataLength = in.readInt(); // 读取传送过来的消息的长度。ByteBuf 的readInt()方法会让他的readIndex增加4
if (dataLength < 0) {
// 我们读到的消息体长度为0,这是不应该出现的情况,这里出现这情况,关闭连接。
ctx.close();
}
if (in.readableBytes() < dataLength) {
//读到的消息体长度如果小于我们传送过来的消息长度,则resetReaderIndex. 这个配合markReaderIndex使用的。把readIndex重置到mark的地方
in.resetReaderIndex();
return;
}
byte[] body = new byte[dataLength]; //传输正常
in.readBytes(body);
Object o = convertToObject(body); //将byte数据转化为我们需要的对象
out.add(o);
}
private Object convertToObject(byte[] body) {
Input input = null;
ByteArrayInputStream bais = null;
try {
bais