LengthFieldBaseFrameDecoderService:
package Netty3;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.net.InetSocketAddress;
public class LengthFieldBaseFrameDecoderService {
private static final int MAX_FRAME_LENGTH = 1024 * 1024;
private static final int LENGTH_FIELD_LENGTH = 4;
private static final int LENGTH_FIELD_OFFSET = 1;
private static final int LENGTH_ADJUSTMENT = 0;
private static final int INITIAL_BYTES_TO_STRIP = 0;
private int port;
public LengthFieldBaseFrameDecoderService(int port) {
this.port = port;
}
public void start(){
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap sbs = new ServerBootstrap()
.group(bossGroup,workerGroup)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new NewServerChannelInitializer(MAX_FRAME_LENGTH,LENGTH_FIELD_LENGTH,LENGTH_FIELD_OFFSET,LENGTH_ADJUSTMENT,INITIAL_BYTES_TO_STRIP))
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = sbs.bind(port).sync();
System.out.println("Server start listen at " + port );
future.channel().closeFuture().sync();
} catch (Exception e) {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
LengthFieldBaseFrameDecoderService server = new LengthFieldBaseFrameDecoderService(7788);
server.start();
}
}
NewServerChannelInitializer:
package Netty3;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
public class NewServerChannelInitializer extends ChannelInitializer<SocketChannel> {
private final int MAX_FRAME_LENGTH;
private final int LENGTH_FIELD_LENGTH;
private final int LENGTH_FIELD_OFFSET;
private final int LENGTH_ADJUSTMENT;
private final int INITIAL_BYTES_TO_STRIP;
public NewServerChannelInitializer(int MAX_FRAME_LENGTH, int LENGTH_FIELD_LENGTH, int LENGTH_FIELD_OFFSET, int LENGTH_ADJUSTMENT, int INITIAL_BYTES_TO_STRIP) {
this.MAX_FRAME_LENGTH = MAX_FRAME_LENGTH;
this.LENGTH_FIELD_LENGTH = LENGTH_FIELD_LENGTH;
this.LENGTH_FIELD_OFFSET = LENGTH_FIELD_OFFSET;
this.LENGTH_ADJUSTMENT = LENGTH_ADJUSTMENT;
this.INITIAL_BYTES_TO_STRIP = INITIAL_BYTES_TO_STRIP;
}
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new NewDecoder(MAX_FRAME_LENGTH,LENGTH_FIELD_LENGTH,LENGTH_FIELD_OFFSET,LENGTH_ADJUSTMENT,INITIAL_BYTES_TO_STRIP,false));
// 自己的逻辑Handler
pipeline.addLast(new NewEncoder());
pipeline.addLast("handler0", new NewServerHandler());
}
}
NewServerHandler:
package Netty3;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class NewServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
if(o instanceof Message) {
Message msg = (Message)o;
System.out.println("Client->Server:"+channelHandlerContext.channel().remoteAddress()+" send "+msg.getMsgBody());
String m = "OK.I Get Your Message.";
Message msg1 = new Message((byte)0xCA, m.length(), m);
channelHandlerContext.writeAndFlush(msg1);
}
}
}
Message:
package Netty3;
public class Message {
//消息类型
private byte type;
//消息长度
private int length;
//消息体
private String msgBody;
public Message(byte type, int length, String msgBody) {
this.type = type;
this.length = length;
this.msgBody = msgBody;
}
public byte getType() {
return type;
}
public void setType(byte type) {
this.type = type;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public String getMsgBody() {
return msgBody;
}
public void setMsgBody(String msgBody) {
this.msgBody = msgBody;
}
}
NewDecoder:
package Netty3;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import java.nio.charset.Charset;
public class NewDecoder extends LengthFieldBasedFrameDecoder {
/**
* 我们在Message类中定义了type和length,这都放在消息头部
* type占1个字节,length占4个字节所以头部总长度是5个字节
*/
private static final int HEADER_SIZE = 5;
private byte type;
private int length;
private String msgBody;
/**
*
* @param maxFrameLength 网络字节序,默认为大端字节序
* @param lengthFieldOffset 消息中长度字段偏移的字节数
* @param lengthFieldLength 数据帧的最大长度
* @param lengthAdjustment 该字段加长度字段等于数据帧的长度
* @param initialBytesToStrip 从数据帧中跳过的字节数
* @param failFast 如果为true,则表示读取到长度域,TA的值的超过maxFrameLength,就抛出一个 TooLongFrameException
*/
public NewDecoder(int maxFrameLength, int lengthFieldOffset,
int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip,
boolean failFast) {
super(maxFrameLength, lengthFieldOffset, lengthFieldLength,
lengthAdjustment, initialBytesToStrip, failFast);
}
@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
if(in == null){
return null;
}
if(in.readableBytes() < HEADER_SIZE){
throw new Exception("错误的消息");
}
/**
* 通过源码我们能看到在读的过程中
* 每读一次读过的字节即被抛弃
* 即指针会往前跳
*/
type = in.readByte();
System.out.println("类型:"+type);
length = in.readByte();
System.out.println("长度:"+length);
if(in.readableBytes() < length){
throw new Exception("消息不正确");
}
ByteBuf buf = in.readBytes(length);
System.out.println("内容:"+buf.toString(Charset.defaultCharset()));
byte[] b = new byte[buf.readableBytes()];
buf.readBytes(b);
msgBody = new String(b,"UTF-8");
Message msg = new Message(type,length,msgBody);
return msg;
}
}
NewEncoder:
package Netty3;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.nio.charset.Charset;
public class NewEncoder extends MessageToByteEncoder<Message> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Message message, ByteBuf byteBuf) throws Exception {
if(message == null){
throw new Exception("未获得消息内容");
}
String msgBody = message.getMsgBody();
byte[] b = msgBody.getBytes(Charset.forName("utf-8"));
byteBuf.writeByte(message.getType());
byteBuf.writeByte(b.length);
byteBuf.writeBytes(b);
}
}
LengthFieldBaseFrameDecoderClient:
package Netty3;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.AttributeKey;
public class LengthFieldBaseFrameDecoderClient {
private static final int MAX_FRAME_LENGTH = 1024 * 1024;
private static final int LENGTH_FIELD_LENGTH = 4;
private static final int LENGTH_FIELD_OFFSET = 1;
private static final int LENGTH_ADJUSTMENT = 0;
private static final int INITIAL_BYTES_TO_STRIP = 0;
private int port;
private String address;
public LengthFieldBaseFrameDecoderClient(int port,String address) {
this.port = port;
this.address = address;
}
public void start(){
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new NewClientChannelInitializer(MAX_FRAME_LENGTH,LENGTH_FIELD_LENGTH,LENGTH_FIELD_OFFSET,LENGTH_ADJUSTMENT,INITIAL_BYTES_TO_STRIP));
try {
ChannelFuture future = bootstrap.connect(address,port).sync();
future.channel().closeFuture().sync();
/* AttributeKey<String> key = AttributeKey.valueOf("ServerData");
Object result = future.channel().attr(key).get();
System.out.println(result.toString());*/
} catch (Exception e) {
e.printStackTrace();
}finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) {
LengthFieldBaseFrameDecoderClient client = new LengthFieldBaseFrameDecoderClient(7788,"127.0.0.1");
client.start();
}
}
NewClientChannelInitializer:
package Netty3;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.AttributeKey;
import java.nio.charset.Charset;
public class NewClientChannelInitializer extends ChannelInitializer<SocketChannel> {
private final int MAX_FRAME_LENGTH;
private final int LENGTH_FIELD_LENGTH;
private final int LENGTH_FIELD_OFFSET;
private final int LENGTH_ADJUSTMENT;
private final int INITIAL_BYTES_TO_STRIP;
public NewClientChannelInitializer(int MAX_FRAME_LENGTH, int LENGTH_FIELD_LENGTH, int LENGTH_FIELD_OFFSET, int LENGTH_ADJUSTMENT, int INITIAL_BYTES_TO_STRIP) {
this.MAX_FRAME_LENGTH = MAX_FRAME_LENGTH;
this.LENGTH_FIELD_LENGTH = LENGTH_FIELD_LENGTH;
this.LENGTH_FIELD_OFFSET = LENGTH_FIELD_OFFSET;
this.LENGTH_ADJUSTMENT = LENGTH_ADJUSTMENT;
this.INITIAL_BYTES_TO_STRIP = INITIAL_BYTES_TO_STRIP;
}
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new NewEncoder());
pipeline.addLast(new NewClientHandler());
pipeline.addLast(new NewDecoder(MAX_FRAME_LENGTH,LENGTH_FIELD_LENGTH,LENGTH_FIELD_OFFSET,LENGTH_ADJUSTMENT,INITIAL_BYTES_TO_STRIP,false));
/*pipeline.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ByteBuf) {
String value = ((ByteBuf) msg).toString(Charset.defaultCharset());
System.out.println("返回:" + value);
}
AttributeKey<String> key = AttributeKey.valueOf("ServerData");
ctx.channel().attr(key).set("客户端处理完毕");
ctx.close();
}
});*/
}
}
NewClientHandler:
package Netty3;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class NewClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
for (int i=0;i<10;i++){
String m = "你好啊,Netty。";
Message msg = new Message((byte)0xCA, m.length(), m);
ctx.writeAndFlush(msg);
}
}
}