刚刚工作的时候(虽然现在也是刚刚工作)接触过Netty,不过那时候小白(现在依然是),不知道Netty是个什么东西,甚至都不知道NIO,只知道工程的框架里用了Netty。后来超哥(我眼里的大神)告诉我学学NIO,然后了解一下Netty框架,所以小白谨遵教诲,如今抽出时间仔细的从基础学起,直到用Netty发送字节信息的时候都还算顺利,但是昨天准备发送自定义消息的时候出了问题,通道可以建立起来,但是发送却总是不成功,后来百度、谷歌、stackoverflow了一下,原来是编码与解码的问题。Netty是NIO框架,所以能传字节是必须的,但是传输对象的时候就有了问题,缓冲区里传的还是字节数组,而我们要传一个对象,所以这就需要我们把对象转化为字节数组写入缓冲区传输,接收的时候将字节数组读出并转化为对象,只有这样,自定义的消息才能在客户端与服务器之间传输,当然,传输的消息要实现Serializable接口。
最后只要在设置Handler的时候设置这两个编码、解码器就可以了。
以下上干货,工具类
package org.aurora.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import io.netty.buffer.ByteBuf;
public class Util {
public static byte[] readBuffer(ByteBuf buffer){
byte[] bs = new byte[buffer.readableBytes()];
buffer.readBytes(bs);
return bs;
}
public static byte[] object2Bytes(Object obj){
byte[] bs = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
bs = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
oos.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bs;
}
public static Object bytes2Object(byte[] bs){
Object obj = null;
ByteArrayInputStream bis = new ByteArrayInputStream(bs);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bis);
obj = ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
try {
ois.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
}
自定义消息
package org.aurora.model;
import java.io.Serializable;
public class Commond implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String content;
public Commond(String content){
this.content = content;
}
public String getContent(){
return content;
}
}
编码
package org.aurora.util;
import org.aurora.model.Commond;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
public class CommondEncoder extends MessageToByteEncoder<Commond>{
@Override
protected void encode(ChannelHandlerContext ctx, Commond msg, ByteBuf out)
throws Exception {
// 将对象转化为字节数组
byte[] bs = Util.object2Bytes(msg);
// 将字节数组写入缓冲区
out.writeBytes(bs);
ctx.flush();
}
}
解码
package org.aurora.util;
import java.util.List;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
public class CommondDecoder extends ByteToMessageDecoder{
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in,
List<Object> out) throws Exception {
// 读取ByteBuf中的流数据,读出字节数组
byte[] bs = Util.readBuffer(in);
// 将字节数组转化为对象
Object obj = Util.bytes2Object(bs);
// 将对象放入list
out.add(obj);
}
}
最后只要在设置Handler的时候设置这两个编码、解码器就可以了。