Netty 是一个基于NIO的客户,服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
主要特性如下:
- API使用简单,开发门槛低;
- 功能强大,预置了多种编解码功能,支持多种主流协议;
- 定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展;
- 性能高,通过与其他业界主流的NIO框架对比,Netty的综合性能最优;
- 成熟、稳定,Netty修复了已经发现的所有JDK NIO Bug,业务开发人员不需要再为NIO的Bug而烦恼;
- 社区活跃,版本迭代周期短,发现的Bug可以被及时修复,同时,更多的新功能会加入;
- 经历了大规模的商业应用考验,质量得到验证。
http://ifeve.com/netty5-user-guide/
package net.netty.demo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
public class Server {
private int port;
public Server(int port) {
this.port = port;
}
public void start() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap boot = new ServerBootstrap();
boot.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc)
throws Exception {
// 1. 解决TCP拆包/粘包问题,通过标示符
ByteBuf buf = Unpooled.copiedBuffer("|".getBytes());
DelimiterBasedFrameDecoder decoder = new DelimiterBasedFrameDecoder(
100, buf);
sc.pipeline().addLast(decoder);
sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(new ServetHandler());
}
}).option(ChannelOption.SO_BACKLOG, 128)
.option(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = boot.bind(port).sync();
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
Server server = new Server(8086);
try {
server.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package net.netty.demo;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import java.util.concurrent.atomic.AtomicInteger;
public class ServetHandler extends ChannelHandlerAdapter {
private AtomicInteger atomicInt = new AtomicInteger();
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg)
throws Exception {
String revice = (String) msg;
System.out.println("Servet Revice:" + revice);
System.out.flush();
ChannelFuture future = ctx
.writeAndFlush(Unpooled.copiedBuffer(("service revice"
+ atomicInt.incrementAndGet() + "|").getBytes()));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
}
}
package net.netty.demo;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
public class Client {
public void start() throws InterruptedException {
EventLoopGroup worker = new NioEventLoopGroup();
try {
Bootstrap boot = new Bootstrap();
boot.group(worker).channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc)
throws Exception {
ByteBuf buf = Unpooled.copiedBuffer("|".getBytes());
sc.pipeline().addLast(
new DelimiterBasedFrameDecoder(100, buf));
sc.pipeline().addLast(new StringDecoder());
sc.pipeline().addLast(new ClientHandler());
}
}).option(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture future = boot.connect("127.0.0.1", 8086).sync();
future.channel().writeAndFlush(
Unpooled.copiedBuffer("aaa|".getBytes()));
future.channel().writeAndFlush(
Unpooled.copiedBuffer("bbbb|".getBytes()));
future.channel().writeAndFlush(
Unpooled.copiedBuffer("ccccc|".getBytes()));
future.channel().closeFuture().sync();
} finally {
worker.shutdownGracefully();
}
}
public static void main(String[] args) {
Client client = new Client();
try {
client.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package net.netty.demo;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class ClientHandler extends ChannelHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
String revice = (String) msg;
System.out.println("Servet Revice:" + revice);
System.out.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
}
}