Netty 是一个异步的、事件驱动的网络编程框架,可以快速开发出可维护的、高性能、高扩展能力的协议服务及其客户端应用。
Netty 是一个基于NIO的客户端、服务器端编程框架,使用Netty可以确保你快速简单的开发出一个网络应用。例如实现了某种协议的客户端、服务端应用。Netty简化了网络应用的编程开发过程,例如:TCP和UDP的socket服务开发。
“快速”和“简单”并不意味着会让你的最终应用产生维护性或性能上的问题。Netty 是一个吸收了多种协议的实现经验,这些协议包括FTP、SMTP、HTTP、各种二进制、文本协议,并经过相当精心设计的项目,最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。
jar包依赖:
<dependency> <groupId>org.jboss.netty</groupId> <artifactId>netty</artifactId> <version>3.2.0.ALPHA4</version> </dependency>
public void testServer() { ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap(factory); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new ServerHandler(), new TimeEncoder()); } }); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); bootstrap.bind(new InetSocketAddress("localhost", 9999)); }
两个ChannelHandler处理类
ServerHandler.java
public class ServerHandler extends SimpleChannelHandler { @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { Person person = new Person("Tom哥", 29, 111111111); ChannelFuture future = e.getChannel().write(person); future.addListener(ChannelFutureListener.CLOSE); } }
public class TimeEncoder extends SimpleChannelHandler { private final ChannelBuffer buffer = dynamicBuffer(); @Override public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Person person = (Person) e.getMessage(); buffer.writeInt(person.getName().getBytes("GBK").length); buffer.writeBytes(person.getName().getBytes("GBK")); buffer.writeInt(person.getAge()); buffer.writeDouble(person.getSalary()); Channels.write(ctx, e.getFuture(), buffer); } }
客户端:
public void testClient() { // 创建客户端channel的辅助类,发起connection请求 ClientBootstrap bootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("decoder", new TimeDecoder()); pipeline.addLast("handler", new ClientHandler()); return pipeline; } }); // 创建无连接传输channel的辅助类(UDP),包括client和server ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost", 9999)); future.getChannel().getCloseFuture().awaitUninterruptibly(); bootstrap.releaseExternalResources(); }
1) 使用NioClientSocketChannelFactory而不是NioServerSocketChannelFactory来创建客户端的Channel通道对象。
2) 客户端的ClientBootstrap对应ServerBootstrap。
3) 请注意,这里不使用“child.”前缀的配置项,客户端的SocketChannel实例不存在父级Channel对象。
4) 我们应当调用connect连接方法,而不是之前的bind绑定方法。
public class TimeDecoder extends FrameDecoder { private final ChannelBuffer buffer = dynamicBuffer(); @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer channelBuffer) throws Exception { if (channelBuffer.readableBytes() < 4) { return null; } if (channelBuffer.readable()) { // 读到,并写入buf channelBuffer.readBytes(buffer, channelBuffer.readableBytes()); } int namelength = buffer.readInt(); String name = new String(buffer.readBytes(namelength).array(), "GBK"); int age = buffer.readInt(); double salary = buffer.readDouble(); Person person = new Person(name, age, salary); return person; } }
+-----+-----+-----+
| ABC | DEF | GHI |
+-----+-----+-----+
由于这种流传输协议的普遍性质,在你的应用中有较高的可能会把这些数据读取为另外一种形式:
+----+-------+---+---+
| AB | CDEFG | H | I |
+----+-------+---+---+
因此对于数据的接收方,不管是服务端还是客户端,应当重构这些接收到的数据,让其变成一种可让你的应用逻辑易于理解的更有意义的数据结构。在上面所述的这个例子中,接收到的数据应当重构为下面的形式:
+-----+-----+-----+
| ABC | DEF | GHI |
+-----+-----+-----+
原文:http://blog.csdn.net/itomge/article/details/21482369