Netty4.x中文教程系列(四)  对象传输

  我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持。

  首先我们定义一个User对象,一定要实现Serializable接口:

package mjorcen.netty.object;

import java.io.Serializable;

/**
* User: hupeng Date: 14-6-3 Time: 上午1:31
*/
public class User implements Serializable { private int id; private String name; private String cardNo; private String description; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getCardNo() {
return cardNo;
} public void setCardNo(String cardNo) {
this.cardNo = cardNo;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} @Override
public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + ", cardNo='"
+ cardNo + '\'' + ", description='" + description + '\'' + '}';
}
}

服务端和客户端里,我们自定义的Handler实现如下:

server

package mjorcen.netty.object;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder; public class ObjectTranferServer { private final int port; public ObjectTranferServer(int port) {
this.port = port;
} public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new ObjectEncoder(),
new ObjectDecoder(Integer.MAX_VALUE,ClassResolvers.cacheDisabled(null)),
new ObjectTransferServerHandler());
}
}); // Bind and start to accept incoming connections.
b.bind(port).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
} public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 11000;
}
new ObjectTranferServer(port).run();
}
}

serverHandler

package mjorcen.netty.object;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.logging.Level;
import java.util.logging.Logger; public class ObjectTransferServerHandler extends ChannelInboundHandlerAdapter { private static final Logger logger = Logger
.getLogger(ObjectTransferServerHandler.class.getName()); @Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
System.out.println(msg);
ctx.writeAndFlush(msg); } // @Override
// public void channelReadComplete(ChannelHandlerContext ctx) throws
// Exception {
// ctx.flush();
// ctx.close();
// } @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
logger.log(Level.WARNING, "Unexpected exception from downstream.",
cause);
ctx.close();
} }

client

package mjorcen.netty.object;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder; public class ObjectTransferClient {
private String host; private int port; private int messageSize; public ObjectTransferClient(String host, int port, int messageSize) {
this.host = host;
this.port = port;
this.messageSize = messageSize;
} public void run() throws InterruptedException {
Bootstrap bootstrap = new Bootstrap();
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try {
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new ObjectEncoder(),
new ObjectDecoder(Integer.MAX_VALUE ,ClassResolvers.cacheDisabled(null)),
new ObjectTransferClientHandler(messageSize));
}
}); ChannelFuture future = bootstrap.connect(host, port).sync(); future.channel().closeFuture().sync();
} finally {
eventLoopGroup.shutdownGracefully();
}
} public static void main(String[] args) throws Exception {
final String host = "localhost";
final int port = 11000;
final int messageSize = 20; new ObjectTransferClient(host, port, messageSize).run();
}
}

clientHandler

package mjorcen.netty.object;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger; public class ObjectTransferClientHandler extends ChannelInboundHandlerAdapter { private static final Logger logger = Logger
.getLogger(ObjectTransferClientHandler.class.getName()); private final List<User> message; /**
* Creates a client-side handler.
*/
public ObjectTransferClientHandler(int messageSize) {
if (messageSize <= 0) {
throw new IllegalArgumentException("firstMessageSize: "
+ messageSize);
}
message = new ArrayList<User>(messageSize);
for (int i = 0; i < messageSize; i++) {
User user = new User();
user.setId(i);
user.setCardNo("420000" + i);
user.setName("hu" + i);
user.setDescription("你觉得这样好吗??真的好吗" + i);
message.add(user); }
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// Send the message to Server
super.channelActive(ctx);
ctx.writeAndFlush(message);
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
// you can use the Object from Server here
System.out.println(msg);
ctx.close();
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
logger.log(Level.WARNING, "Unexpected exception from downstream.",
cause);
ctx.close();
}
}

简单梳理一下思路:

  1. 通过Netty传递,都需要基于流,以ChannelBuffer的形式传递。所以,Object -> ChannelBuffer.
  2. Netty提供了转换工具,需要我们配置到Handler。
  3. 样例从客户端 -> 服务端,单向发消息,所以在客户端配置了编码,服务端解码。如果双向收发,则需要全部配置Encoder和Decoder。

  这里需要注意,注册到Server的Handler是有顺序的,如果你颠倒一下注册顺序:

  结果就是,会先进入我们自己的业务,再进行解码。这自然是不行的,会强转失败。至此,你应该会用Netty传递对象了吧。

Netty4.x中文教程系列(四) 对象传输的更多相关文章

  1. Netty4.x中文教程系列(四) ChannelHandler

    这篇文章用以解释ChannelHandler.笔者本身在以前写过文章ChannelHandler改动及影响 和 ChannelInitializer 学习 对Netty的.ChannelHandler ...

  2. Netty4.x中文教程系列(一) 目录及概述

    Netty4.x中文教程系列(一)目录及概述 Netty 提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. Netty是一个NIO客户端 服务端框架 ...

  3. Netty4.x中文教程系列(三) ChannelHandler

    Netty4.x中文教程系列(四)  ChannelHandler 上一篇文章详细解释了Hello World示例的代码.里面涉及了一些Netty框架的基础. 这篇文章用以解释ChannelHandl ...

  4. Netty4.x中文教程系列(五)编解码器Codec

    Netty4.x中文教程系列(五)编解码器Codec 上一篇文章详细解释了ChannelHandler的相关构架设计,版本和设计逻辑变更等等. 这篇文章主要在于讲述Handler里面的Codec,也就 ...

  5. Netty4.x中文教程系列(六) 从头开始Bootstrap

    Netty4.x中文教程系列(六) 从头开始Bootstrap 其实自从中文教程系列(五)一直不知道自己到底想些什么.加上忙着工作上出现了一些问题.本来想就这么放弃维护了.没想到有朋友和我说百度搜索推 ...

  6. Netty4.x中文教程系列(二) Hello World !

    在中国程序界.我们都是学着Hello World !慢慢成长起来的.逐渐从一无所知到熟悉精通的. 第二章就从Hello World 开始讲述Netty的中文教程. 首先创建一个Java项目.引入一个N ...

  7. Netty4.x中文教程系列(二) Hello World !<转>

    在中国程序界.我们都是学着Hello World !慢慢成长起来的.逐渐从一无所知到熟悉精通的. 第二章就从Hello World 开始讲述Netty的中文教程. 首先创建一个Java项目.引入一个N ...

  8. struts2官方 中文教程 系列四:Action

    先贴个本帖的地址,免得其它网站被爬去了struts2教程 官方系列四:Action  即 http://www.cnblogs.com/linghaoxinpian/p/6905521.html 下载 ...

  9. Netty4.x中文教程系列(三) Hello World !详解

    Netty 中文教程 (二) Hello World !详解 上一篇文章,笔者提供了一个Hello World 的Netty示例. 时间过去了这么久,准备解释一下示例代码. 1.HelloServer ...

随机推荐

  1. 正确理解SQL Server的许可证(转)

    今天在论坛上看到有人讨论如果使用SQL Server作为SEPM的后台数据库,需要多少个CAL的问题:   If I do have to use SQL Server what type of li ...

  2. Java之经典Student问题2

    创建5个学生对象给一个学生数组赋值,每个学生属性有:学号.姓名.年龄. 要求:1.给每个学生排序输出.  2.给所有学生年龄加1.  3.统计年龄大于20的学生人数. 在这里,我们用了compareT ...

  3. lua定时器与定时任务的接口设计

    在所有的服务器编程当中,定时任务永远是一个不可或缺的需求.最直接的需求就是,每天凌晨0点0分的时候总是有一大堆的各种精力重置.怎么来设计这个接口呢,想了几个方案: 每秒触发 每分钟触发 每整点触发 每 ...

  4. ROS ZYNQ移植

    1  准备工作 全部是按照官方操作的:http://wiki.ros.org/groovy/Installation/Source   apt-get install python-rosdep py ...

  5. c++11:iota

    iota: Fills the range [first, last) with sequentially(循环的) increasing values, starting with value an ...

  6. 第四届蓝桥杯C/C++A组题目:振兴中华

    首先把题目贴上来吧! 小明参加了学校的趣味运动会,其中的一个项目是:跳格子. 地上画着一些格子,每个格子里写一个字,如下所示:(也可参见图1) 从我做起振 我做起振兴 做起振兴中 起振兴中华 图1 比 ...

  7. ADO.NET笔记——使用Connection连接数据库,使用Command对象的ExecuteReader()方法创建DataReader对象返回多行数据

    使用Connection连接数据库,使用DataReader访问数据库,并返回多行数据. 相关步骤: 需要引入两个命名空间 using System.Data; using System.Data.S ...

  8. 前端工程搭建NodeJs+gulp+bower

    需要node.npm的事先安装!! 1.nodejs安装程序会在环境变量中添加两个变量: 系统环境变量中:path 增加C:\Program Files\nodejs\ 因为在该目下存在node.ex ...

  9. JavaScript 中的 replace 方法

    定义和用法 replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. stringObject.replace(regexp/substr,replaceme ...

  10. struts2 type="redirect"源码解析

    首先解释一下几个名词: request.getRequestDispatcher()是请求转发,前后页面共享一个request ; response.sendRedirect()是重新定向,前后页面不 ...