您的位置:首页 > 其它

Netty快速入门

2018-02-22 18:32 399 查看

Netty快速入门

异步非阻塞IO

什么是Netty

Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。

Netty应用场景

1.分布式开源框架中dubbo、Zookeeper,RocketMQ,底层rpc通讯使用就是netty。

2.游戏开发中,底层使用netty通讯。

为什么选择netty

因为可以解决NIO代码复杂问题,以及有更好的容错机制!

那么为什么不建议开发者直接使用JDK的NIO类库进行开发?

1) NIO的类库和API繁杂,使用麻烦,你需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等;

2) 需要具备其它的额外技能做铺垫 。

例如:熟悉Java多线程编程,因为NIO编程涉及到Reactor模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的NIO程序;

3) 可靠性能力补齐,工作量和难度都非常大。

例如:客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等等,NIO编程的特点是功能开发相对容易,但是可靠性能力补齐工作量和难度都非常大;

4) JDK NIO的BUG。

例如:臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该bug发生概率降低了一些而已,它并没有被根本解决。

代码示例

Maven坐标

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
<version>3.10.5.Final</version>
</dependency>


Netty服务器端

public class NettyServer {
public static void main(String[] args) {
//创建服务类对象
ServerBootstrap serverBootstrap = new ServerBootstrap();
//创建两个线程池,分别为监听端口,监听NIO
ExecutorService boos = Executors.newCachedThreadPool();
ExecutorService worker = Executors.newCachedThreadPool();
//设置工程,并把两个线程池加入其中
serverBootstrap.setFactory(new NioServerSocketChannelFactory(boos,worker));
//设置管道工程
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
//将数据转换为String类型
pipeline.addLast("decoder",new StringDecoder());
pipeline.addLast("encoder",new StringEncoder());
pipeline.addLast("serverHandler",new ServerHandler());
return pipeline;
}
});
//绑定端口号
serverBootstrap.bind(new InetSocketAddress(8080));
System.out.println("Netty服务器端已经启动...");

}
}

class ServerHandler extends SimpleChannelHandler{
/**
* 通道关闭的时候触发
*/
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("通道关闭的时候触发:channelClosed");
}
/**
* 必须是连接已经建立,关闭通道的时候才会触发
*/
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("必须是连接已经建立,关闭通道的时候才会触发:channelDisconnected");
}
/**
* 捕获异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println("捕获异常:exceptionCaught");
}
/**
* 接受消息
*/
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("服务器端接受到客户端的消息:"+e.getMessage());
//回复内容
ctx.getChannel().write("您好,主人暂时不在,有事请留言!!!");
}
}


Netty客户端

public class NettyClient {
public static void main(String[] args) {
System.out.println("Netty客户端已经启动...");
//创建服务类对象
ClientBootstrap clientBootstrap = new ClientBootstrap();
//创建两个线程池,分别为监听端口,监听NIO
ExecutorService boos = Executors.newCachedThreadPool();
ExecutorService worker = Executors.newCachedThreadPool();
//设置工程,并把两个线程池加入其中
clientBootstrap.setFactory(new NioClientSocketChannelFactory(boos,worker));
//设置管道工程
clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
//将数据转换为String类型
pipeline.addLast("decoder",new StringDecoder());
pipeline.addLast("encoder",new StringEncoder());
pipeline.addLast("clientHandler",new ClientHandler());
return pipeline;
}
});
//连接服务端
ChannelFuture connect = clientBootstrap.connect(new InetSocketAddress("127.0.0.1", 8080));
Channel channel = connect.getChannel();
System.out.println("Client Start");
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请输入内容:");
String str = scanner.next();
channel.write(str);
}

}
}

class ClientHandler extends SimpleChannelHandler {
/**
* 通道关闭的时候触发
*/
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("通道关闭的时候触发:channelClosed");
}
/**
* 必须是连接已经建立,关闭通道的时候才会触发
*/
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("必须是连接已经建立,关闭通道的时候才会触发:channelDisconnected");
}
/**
* 捕获异常
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
System.out.println("捕获异常:exceptionCaught");
}
/**
* 接受消息
*/
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("服务器端向客户端回复内容:"+e.getMessage());
//回复内容
//        ctx.getChannel().write("您好,主人暂时不在,有事请留言!!!");
}
}


运行结果

服务器端:



客户端:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐