浅谈Java的IO与Netty

一、Java的IO((Input/Output))模型

传统IO和Java NIO最大的区别是传统的IO是面向流,NIO是面向Buffer
Socket之间建立链接及通信的过程!实际上就是对TCP/IP连接与通信过程的抽象:
1.服务端Socket会bind到指定的端口上,Listen客户端的”插入”
2.客户端Socket会Connect到服务端
3.当服务端Accept到客户端连接后
4.就可以进行发送与接收消息了
5.通信完成后即可Close

1、BIO(阻塞)

1.socketServer的accept方法是阻塞的;
2.获得连接的顺序是和客户端请求到达服务器的先后顺序相关;
3.适用于一个线程管理一个通道的情况;因为其中的流数据的读取是阻塞的;
4.适合需要管理同时打开不太多的连接,这些连接会发送大量的数据。

浅谈Java的IO与Netty_第1张图片 BIO模型

 

客户端代码
    //Bind,Connect
    Socket client = new Socket("127.0.0.1",7777);
    //读写
    PrintWriter pw = new PrintWriter(client.getOutputStream());
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    pw.write(br.readLine());
    //Close
    pw.close();
    br.close();

服务端代码
    Socket socket;
    //Bind,Listen
    ServerSocket ss = new ServerSocket(7777);
    while (true) {
    //Accept
    socket = ss.accept();
    //一般新建一个线程执行读写
    BufferedReader br = new BufferedReader(
       new InputStreamReader(socket .getInputStream()));
       System.out.println("you input is : " + br.readLine());
    }

2、NIO(非阻塞)

1.基于事件驱动,当有连接请求,会将此连接注册到多路复用器上(selector);
2.在多路复用器上可以注册监听事件,比如监听accept、read;
3.通过监听,当真正有请求数据时,才来处理数据;
4.会不停的轮询是否有就绪的事件,所以处理顺序和连接请求先后顺序无关,与请求数据到来的先后顺序有关;
5.优势在于一个线程管理多个通道;但是数据的处理将会变得复杂;
6.适合需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据。

浅谈Java的IO与Netty_第2张图片 NIO模型

 

浅谈Java的IO与Netty_第3张图片 IO复用模型
NIO客户端
//连接
    //获取socket通道
    SocketChannel channel = SocketChannel.open();
    channel.configureBlocking(false);
    //获得通道管理器
    selector=Selector.open();
    channel.connect(new InetSocketAddress(serverIp, port));
    //为该通道注册SelectionKey.OP_CONNECT事件
    channel.register(selector, SelectionKey.OP_CONNECT);
//监听
    while(true){
        //选择注册过的io操作的事件(第一次为SelectionKey.OP_CONNECT)
        selector.select();
        while(SelectionKey key : selector.selectedKeys()){
            if(key.isConnectable()){
                SocketChannel channel=(SocketChannel)key.channel();
                if(channel.isConnectionPending()){
                    channel.finishConnect();//如果正在连接,则完成连接
                }
                channel.register(selector, SelectionKey.OP_READ);
            }else if(key.isReadable()){ //有可读数据事件。
                SocketChannel channel = (SocketChannel)key.channel();
                ByteBuffer buffer = ByteBuffer.allocate(10);
                channel.read(buffer);
                byte[] data = buffer.array();
                String message = new String(data);
                System.out.println("recevie message from server:, size:" + buffer.position() + " msg: " + message);
            }
        }
    }

服务端
//连接
    //获取一个ServerSocket通道
    ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(false);
    serverChannel.socket().bind(new InetSocketAddress(port));
    //获取通道管理器
    selector = Selector.open();
    //将通道管理器与通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,
    serverChannel.register(selector, SelectionKey.OP_ACCEPT);

//监听
    while(true){
        //当有注册的事件到达时,方法返回,否则阻塞。
        selector.select();
        for(SelectionKey key : selector.selectedKeys()){
            if(key.isAcceptable()){
                ServerSocketChannel server = (ServerSocketChannel)key.channel();
                SocketChannel channel = server.accept();
                channel.write(ByteBuffer.wrap(
                new String("send message to client").getBytes()));
                //在与客户端连接成功后,为客户端通道注册SelectionKey.OP_READ事件。
                channel.register(selector, SelectionKey.OP_READ);
            }else if(key.isReadable()){ //有可读数据事件
                SocketChannel channel = (SocketChannel)key.channel();
                ByteBuffer buffer = ByteBuffer.allocate(10);
                int read = channel.read(buffer);
                byte[] data = buffer.array();
                String message = new String(data);
                System.out.println("receive message from client, size:" + buffer.position() + " msg: " + message);
            }
        }
    }

二、Netty的IO

你可能感兴趣的:(java,开发语言)