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