Netty是一个高性能的NIO通信框架,提供异步的、事件驱动的网络编程模型。使用Netty可以方便用户开发各种常用协议的网络程序。例如:TCP、UDP、HTTP等等。
Netty的最新版本是3.2.7,官网地址是:http://www.jboss.org/netty
本文的主要目的是基于Netty实现一个通用二进制协议的高效数据传输。协议是通用的二进制协议,高效并且扩展性很好。
一个好的协议有两个标准:
(1)生成的传输数据要少,即数据压缩比要高。这样可以减少网络开销。
(2)传输数据和业务对象之间的转换速度要快。
(友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hankchen)
一、协议的定义
无论是请求还是响应,报文都由一个通用报文头和实际数据组成。报文头在前,数据在后。
(1)报文头:由数据解析类型,数据解析方法,编码,扩展字节,包长度组成,共16个字节:
编码方式(1byte)、加密(1byte)、扩展1(1byte)、扩展2(1byte)、会话ID(4byte)、命令或者结果码(4byte)、数据包长(4byte)
(2)数据:由数据包长指定。请求或回复数据。类型对应为JAVA的Map<String,String>
数据格式定义:
字段1键名长度 字段1键名 字段1值长度 字段1值
字段2键名长度 字段2键名 字段2值长度 字段2值
字段3键名长度 字段3键名 字段3值长度 字段3值
… … … …
长度为整型,占4个字节
代码中用两个Vo对象来表示:XLRequest和XLResponse。
1

package org.jboss.netty.example.xlsvr.vo;
2

3

import java.util.HashMap;
4

import java.util.Map;
5

6
![]()
}
1

package org.jboss.netty.example.xlsvr.vo;
2

3

import java.util.HashMap;
4

import java.util.Map;
5

6
二、协议的编码和解码
对于自定义二进制协议,编码解码器往往是Netty开发的重点。这里直接给出相关类的代码。
1

package org.jboss.netty.example.xlsvr.codec;
2

3

import java.nio.ByteBuffer;
4

5

import org.jboss.netty.buffer.ChannelBuffer;
6

import org.jboss.netty.buffer.ChannelBuffers;
7

import org.jboss.netty.channel.ChannelHandlerContext;
8

import org.jboss.netty.channel.Channels;
9

import org.jboss.netty.channel.MessageEvent;
10

import org.jboss.netty.channel.SimpleChannelDownstreamHandler;
11

import org.jboss.netty.example.xlsvr.util.ProtocolUtil;
12

import org.jboss.netty.example.xlsvr.vo.XLResponse;
13

import org.slf4j.Logger;
14

import org.slf4j.LoggerFactory;
15

16
1

package org.jboss.netty.example.xlsvr.codec;
2

3

import org.jboss.netty.buffer.ChannelBuffer;
4

import org.jboss.netty.buffer.ChannelBuffers;
5

import org.jboss.netty.channel.Channel;
6

import org.jboss.netty.channel.ChannelHandlerContext;
7

import org.jboss.netty.example.xlsvr.util.ProtocolUtil;
8

import org.jboss.netty.example.xlsvr.vo.XLResponse;
9

import org.jboss.netty.handler.codec.frame.FrameDecoder;
10

11
![]()
}
1

package org.jboss.netty.example.xlsvr.util;
2

3

import java.net.SocketAddress;
4

import java.nio.charset.Charset;
5

import java.util.HashMap;
6

import java.util.Map;
7

import java.util.Map.Entry;
8

9

import org.jboss.netty.buffer.ChannelBuffer;
10

import org.jboss.netty.buffer.ChannelBuffers;
11

import org.jboss.netty.channel.Channel;
12

13
三、服务器端实现
服务器端提供的功能是:
1、接收客户端的请求(非关闭命令),返回XLResponse类型的数据。
2、如果客户端的请求是关闭命令:shutdown,则服务器端关闭自身进程。
为了展示多协议的运用,这里客户端的请求采用的是基于问本行(\n\r)的协议。
具体代码如下:
1

package org.jboss.netty.example.xlsvr;
2

3

import java.net.InetSocketAddress;
4

import java.util.concurrent.Executors;
5

6

import org.jboss.netty.bootstrap.ServerBootstrap;
7

import org.jboss.netty.channel.Channel;
8

import org.jboss.netty.channel.ChannelPipeline;
9

import org.jboss.netty.channel.group.ChannelGroup;
10

import org.jboss.netty.channel.group.ChannelGroupFuture;
11

import org.jboss.netty.channel.group.DefaultChannelGroup;
12

import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
13

import org.jboss.netty.example.xlsvr.codec.XLServerEncoder;
14

import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
15

import org.jboss.netty.handler.codec.frame.Delimiters;
16

import org.jboss.netty.handler.codec.string.StringDecoder;
17

import org.jboss.netty.util.CharsetUtil;
18

import org.slf4j.Logger;
19

import org.slf4j.LoggerFactory;
20

21
1

package org.jboss.netty.example.xlsvr;
2

3

import java.util.Random;
4

5

import org.jboss.netty.channel.Channel;
6

import org.jboss.netty.channel.ChannelFuture;
7

import org.jboss.netty.channel.ChannelHandlerContext;
8

import org.jboss.netty.channel.ChannelHandler.Sharable;
9

import org.jboss.netty.channel.ChannelStateEvent;
10

import org.jboss.netty.channel.ExceptionEvent;
11

import org.jboss.netty.channel.MessageEvent;
12

import org.jboss.netty.channel.SimpleChannelHandler;
13

import org.jboss.netty.example.xlsvr.vo.XLResponse;
14

import org.slf4j.Logger;
15

import org.slf4j.LoggerFactory;
16

17
四、客户端实现
客户端的功能是连接服务器,发送10次请求,然后发送关闭服务器的命令,最后主动关闭客户端。
关键代码如下:
1
![]()
}
1
![]()
}
1
![]()
}
全文代码较多,写了很多注释,希望对读者有用,谢谢!
(友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hankchen)
http://www.blogjava.net/hankchen/archive/2012/02/04/369378.html