netty进行对象传输首先对象需要序列化,然后通过ByteBuf的形式进行传输!
1 引入pom文件
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.29.Final</version>
</dependency>
2 对象类
public class User implements Serializable{
private String username;
private int age;
public User(String username,int age){
this.username = username;
this.age =age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "username:"+username+",age:"+age;
}
}
3 编写UserDecoder与UserEncoder
3.1 UserDecoder
public class UserDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
ByteBufToBytes read = new ByteBufToBytes();
Object obj = ByteObjConverter.byteToObject(read.read(in));
out.add(obj);
}
}
3.2 UserEncoder
public class UserEncoder extends MessageToByteEncoder<User> {
@Override
protected void encode(ChannelHandlerContext ctx, User user, ByteBuf out) throws Exception {
byte[] datas = ByteObjConverter.objectToByte(user);
out.writeBytes(datas);
ctx.flush();
}
}
3.3 辅助工具类ByteObjConverter
public class ByteObjConverter {
public static Object byteToObject(byte[] bytes) {
Object obj = null;
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ObjectInputStream oi = null;
try {
oi = new ObjectInputStream(bi);
obj = oi.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bi.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
oi.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
public static byte[] objectToByte(Object obj) {
byte[] bytes = null;
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = null;
try {
oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
bytes = bo.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bo.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
oo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
}
3.4 辅助工具类ByteBufToBytes
public class ByteBufToBytes {
public byte[] read(ByteBuf datas) {
byte[] bytes = new byte[datas.readableBytes()];
datas.readBytes(bytes);
return bytes;
}
}
4 Server端构建
4.1 Server
public class Server {
/**
* 用于分配处理业务线程的线程组个数
*/
protected static final int BIZGROUPSIZE = Runtime.getRuntime().availableProcessors()*2; //默认
/**
*业务出现线程大小
*/
protected static final int BIZTHREADSIZE = 4;
/**
* NioEventLoopGroup实际上就是个线程池,
* NioEventLoopGroup在后台启动了n个NioEventLoop来处理Channel事件,
* 每一个NioEventLoop负责处理m个Channel,
* NioEventLoopGroup从NioEventLoop数组里挨个取出NioEventLoop来处理Channel
*/
private static final EventLoopGroup bossGroup = new NioEventLoopGroup(BIZGROUPSIZE);
private static final EventLoopGroup workerGroup = new NioEventLoopGroup(BIZTHREADSIZE);
protected void run() throws Exception {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup);
b.channel(NioServerSocketChannel.class);
b.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("decoder", new UserDecoder());
pipeline.addLast("encoder", new UserEncoder());
pipeline.addLast(new ServerHandler());
}
});
ChannelFuture f = b.bind("xx.xx.xx.xx",9873).sync();
System.out.println("netty server start success...");
/**
* wait until the socket close
*/
f.channel().closeFuture().sync();
shutdown();
}
protected static void shutdown() {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
public static void main(String[] args) throws Exception {
new Server().run();
}
}
4.2 Server Handler
public class ServerHandler extends SimpleChannelInboundHandler<Object> {
/**
* 请求的超时时间
*/
private static final long TIMEOUT = 2*60*1000L;
/**
* cache的过期时间:60s
*/
private static final long MILSECONDS = 1000*60;
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg)
throws Exception {
User user = (User)msg;
ctx.channel().writeAndFlush(user);
}
/**
* Close the connection when an exception is raised.
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) throws Exception {
ctx.close();
}
}
5 Cilent端构建
5.1 Client
public class Client {
public static String HOST = "xx.xx.xx.xx";
public static int PORT = 9873;
public static Bootstrap bootstrap = getBootstrap();
public static Channel channel = getChannel(HOST,PORT);
/**
* 初始化Bootstrap
* @return
*/
public static final Bootstrap getBootstrap(){
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class);
b.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
pipeline.addLast("decoder", new UserDecoder());
pipeline.addLast("encoder", new UserEncoder());
pipeline.addLast("handler", new ClientHandler());
}
});
b.option(ChannelOption.SO_KEEPALIVE, true);
return b;
}
public static final Channel getChannel(String host,int port){
Channel channel = null;
try {
channel = bootstrap.connect(host, port).sync().channel();
} catch (Exception e) {
return null;
}
return channel;
}
public static void sendUser(User user) throws Exception {
System.out.println(channel);
if(channel!=null){
channel.writeAndFlush(user).sync();
}else{
System.out("消息发送失败,连接尚未建立!");
}
}
public static void main(String[] args) throws Exception {
try {
Client.sendUser(new User("kevin.yang",24));
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.2 Client Handler
public class ClientHandler extends SimpleChannelInboundHandler<Object> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg)
throws Exception {
System.out("client接收到服务器返回的消息:"+(User)msg);
}
}