从io到netty

io与线程池优化io:

0、io同步、阻塞
1、io的客户端与线程数的比是1:1;线程池优化后的io是m:n
2、io是面向stream编程,因此一个线程只能等待流处理,因此阻塞

nio:

0、nio同步、非阻塞
1、nio的客户端与线程数比是m:1
2、nio是面向buffer编程,因此一个线程写或者读缓冲区后就可以做其他事情了,因此非阻塞
从io到netty_第1张图片图解:(这不就是在东北吃烧烤吗?)
服务端注册Selector,监听accept事件,当客户端连接后,触发accept事件,服务器构建对应的Channel,并在其上注册Selector,监听读写事件,当发生读写事件后,进行相应的读写处理。

aio:

0、aio异步、非阻塞
1、nio与aio的不同之处(也就是reactor与proactor的不同之处):
Reactor将handle放到selecter,等待可写就绪,然后调用write()写入数据;写完处理后续逻辑;
Proactor调用aoi_write(异步写)后立刻返回,由内核负责写操作,写完后调用相应的回调函数处理后续逻辑(如下图);
可以看出,Reactor被动的等待指示事件的到来并做出反应;它有一个等待的过程,做什么都要先放入到监听事件集合中等待handler可用时再进行操作;
Proactor直接调用异步读写操作,调用完后立刻返回。
2、aio在JDK1.7中,这部分内容被称作NIO.2,主要在Java.nio.channels包下增加了下面四个异步通道:
AsynchronousSocketChannel
AsynchronousServerSocketChannel
AsynchronousFileChannel
AsynchronousDatagramChannel
从io到netty_第2张图片

reactor模型:

(在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作。)
从io到netty_第3张图片
图解:
与NIO流程基本相同,只是将消息相关处理独立到了Handler中。
从io到netty_第4张图片
图解:
reactor主从模型,主Reactor用于响应连接请求,从Reactor用于处理IO操作请求。

netty:

0、Netty是一个异步事件驱动的网络应用程序框架,一个高性能NIO框架,一个Reactor模型的实现
1、可以快速开发可维护的高性能协议服务器和客户端。
2、简化了TCP和UDP套接字服务器等网络编程。
3、connect成功后accept就绪交给boss处理,read就绪与write就绪交给worker处理。
从io到netty_第5张图片

模拟一个聊天程序:(客户端输入字符串发送给服务端,服务端返回反转字符串)

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.GlobalEventExecutor;
 
public class ChatServer extends SimpleChannelInboundHandler  {
 
    private int port;
    int i = 0;
 
    public ChatServer(int port) {
        this.port = port;
    }
 
    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);//目前先不使用多通道了
 
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
        StringBuilder sb = new StringBuilder(s);
        ctx.writeAndFlush( sb.reverse()); //加上.addListener(ChannelFutureListener.CLOSE) 表示告诉客户端,关闭socket连接 完成一次数据传输就关闭连接
        i++;
        System.out.println("处理了"+i+"次");
    }
 
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("ChatClient:"+ctx.channel().remoteAddress()+"在线");
    }
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("ChatClient:"+ctx.channel().remoteAddress()+"异常");
        ctx.close();
    }
 
    public void run() throws InterruptedException {
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boss,worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    .addLast(new StringEncoder())
                                    .addLast(new StringDecoder())
                                    .addLast(ChatServer.this);
                        }
                    }).option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
 
            System.out.println("ChatServer 开启");
            ChannelFuture future = serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();//等待通讯完成,关闭服务器通道,在这个聊天程序中不会关闭
        } finally {
            worker.shutdownGracefully();
            boss.shutdownGracefully();
            System.out.println("ChatServer 关闭了");
        }
    }
}
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class ChatClient extends SimpleChannelInboundHandler {
 
    int port;
    String host;
 
    public ChatClient(String host, int port) {
        this.port = port;
        this.host = host;
    }
 
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
        System.out.println("[" + ctx.channel().remoteAddress() + "]: " + s + "\n");
    }
 
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("ChatClient:"+ctx.channel().remoteAddress()+"在线");
        System.out.println("可以开始向对方发送消息了:");
    }
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("ChatServer:"+ctx.channel().remoteAddress()+"异常");
        ctx.close();
    }
 
    public void run() throws InterruptedException {
        EventLoopGroup loopGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(loopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    .addLast(new StringEncoder())
                                    .addLast(new StringDecoder())
                                    .addLast(ChatClient.this);
                        }
                    });
            System.out.println("ChatClient 开启");
            Channel channel = bootstrap.connect(host, port).sync().channel();
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            while(true){
                channel.writeAndFlush(in.readLine() + "\r\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            loopGroup.shutdownGracefully();
        }
    }
}

你可能感兴趣的:(源码阅读,netty,io,nio,aio,java网络通信)