分布式架构底层基础入门---NIO、BIO对比(下)-NIO思维脑图

一、思维脑图:

本章节,重点聊一下NIO中的多路复用器Selector、SocketChannel、ByteBuffer、SelectorKey

分布式架构底层基础入门---NIO、BIO对比(下)-NIO思维脑图_第1张图片

场景:

客户端向Selector发起连接事件,调用selector.select(),这个方法会阻塞执行,也可以设置超时时间;

服务端收到连接事件,会向ByteBuffer写入信息,之后会向Selector注册读事件;

客户端的selector监听到读事件,这时会读取服务端写入的信息;

注:

多路复用需要采用非阻塞的IO,所以代码需要设置:socketChannel.configureBlocking(false);

分布式架构底层基础入门---NIO、BIO对比(下)-NIO思维脑图_第2张图片

 原理深入分析:

需要分析poll/epoll(Event poll)底层原理,这里不做深入分析.

分布式架构底层基础入门---NIO、BIO对比(下)-NIO思维脑图_第3张图片

 

二、代码示例:

package com.jason.thread.socket.nio.step2;

import com.alibaba.fastjson.JSONObject;
import com.jason.thread.socket.body.ServiceRequest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
 * @program: JasonSpringMybatis
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-10 21:27
 **/
public class NewIoServer {
    private  static Selector   selector;

    public ServiceRequest getRequest() {
        return request;
    }

    public void setRequest(ServiceRequest request) {
        this.request = request;
    }

    private    ServiceRequest request;

    public static void main(String[] args) {
        try {
            //多路复用一定要是非阻塞的
            selector=Selector.open();
            System.out.println(selector.hashCode());
            ServerSocketChannel   serverSocketChannel=ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);//设置连接非阻塞
            serverSocketChannel.bind(new InetSocketAddress(8080));
            //注册连接事件
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            while(true)
            {
                System.out.println("服务端等待获取事件驱动:");
                selector.select();//阻塞调用,由事件驱动
                System.out.println("捕获到事件驱动:");
                Set selectionKeySet= selector.selectedKeys();
                Iterator iterator=selectionKeySet.iterator();
                while(iterator.hasNext())
                {
                    SelectionKey  selectionKey=iterator.next();
                    try {
                        iterator.remove();
                        if(selectionKey.isAcceptable()){//连接事件
                            System.out.println("服务端连接开始:");
                            handlerAccept(selectionKey);
                        }else if(selectionKey.isReadable())//读事件
                        {
                            System.out.println("服务端读开始:");
                            handlerRead(selectionKey);
                        }
                    }catch (IOException e)
                    {
                        selectionKey.cancel();
                        continue;
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void handlerRead(SelectionKey selectionKey) throws Exception {
        SocketChannel   socketChannel=(SocketChannel) selectionKey.channel();
        ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
        try {
            socketChannel.configureBlocking(false);
            socketChannel.read(byteBuffer);
            ServiceRequest  serviceRequest=JSONObject.parseObject(new String(byteBuffer.array()),ServiceRequest.class);
            ServiceRequest.RequestData  requestData=serviceRequest.getData();
            System.out.println("收到来自:["+serviceRequest.getFromTalker()+"] 的消息;消息标题:["+requestData.getTitle()+"]"
                    +";消息内容:["+requestData.getContent()+"]");
            requestData.setTitle("互联网架构师内容");
            requestData.setContent("努力学习,成为一流的架构师");
            serviceRequest.setFromTalker("Tom");
            serviceRequest.setToTalker("Jerry");
            serviceRequest.setData(requestData);
            String response=JSONObject.toJSONString(serviceRequest);
            System.out.println("response="+response);
            byteBuffer.clear();
            socketChannel.write(byteBuffer.wrap(response.getBytes()));
            System.out.println("发送读事件:");
            socketChannel.register(selector,SelectionKey.OP_READ );//注册读驱动
        } catch (IOException e) {
            e.printStackTrace();
            throw new IOException("新建异常");
        }
    }
    private static void handlerAccept(SelectionKey selectionKey) {
        ServerSocketChannel   serverSocketChannel=(ServerSocketChannel)selectionKey.channel();
        try {
            SocketChannel  socketChannel   =serverSocketChannel.accept();
            socketChannel.configureBlocking(false);//设置非阻塞
            System.out.println("连接就绪,注册读事件");
            socketChannel.write(ByteBuffer.wrap("Hello Client,I'am NIO Server!".getBytes()));
            System.out.println("发送读事件:");
            socketChannel.register(selector,SelectionKey.OP_READ );//注册读驱动
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


package com.jason.thread.socket.nio.step2;

import com.alibaba.fastjson.JSONObject;
import com.jason.thread.socket.body.ServiceRequest;
import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @program: JasonSpringMybatis
 * @description
 * @author: 大龄程序猿
 * @create: 2020-06-13 19:36
 **/
public class KeepAlive implements Runnable{
    private  static Selector selector;
    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        executor.scheduleAtFixedRate(new KeepAlive(),1,8, TimeUnit.SECONDS);
    }

    @Override
    public void run() {
        try
        {
            selector=Selector.open();
            System.out.println(selector.hashCode());
            SocketChannel socketChannel=SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("localhost",8080));
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            while(true)
            {
                System.out.println("客户端阻塞等待事件驱动:");
                selector.select(2000);//阻塞
                System.out.println("捕获到事件:");
                Set selectionKeySet = selector.selectedKeys();
                Iterator iterator = selectionKeySet.iterator();
                if(!iterator.hasNext())
                {
                    System.out.println("等待超时,未获取到服务端的响应,当前线程退出!!");
                    break;
                }
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    System.out.println("SelectionKey=="+key.hashCode());
                    iterator.remove();
                    if (key.isConnectable())//连接事件
                    {
                        System.out.println("客户端连接开始:");
                        handleSocketChannel(key);
                    }else if(key.isReadable())
                    {
                        System.out.println("客户端读开始:");
                        HandleRead(key);
                    }
                }
            }

        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    private static void HandleRead(SelectionKey key) throws IOException {
        SocketChannel socketChannel=(SocketChannel)key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        socketChannel.read(buffer);
        System.out.println(new String(buffer.array()));
    }

    private static void handleSocketChannel(SelectionKey key) throws IOException {
        SocketChannel   channel=(SocketChannel)key.channel();
        if(channel.isConnectionPending())
        {
            channel.finishConnect();
        }
        channel.configureBlocking(false);
        channel.write(ByteBuffer.wrap(initRequest().getBytes()));
        channel.register(selector,SelectionKey.OP_READ);
    }

    @Test
    public static String initRequest()
    {
        ServiceRequest request=new ServiceRequest(true,"jerry","Jaosn");
        ServiceRequest.RequestData   requestData= request.new RequestData("AA","CC");
        request.setData(requestData);
        String jason= JSONObject.toJSONString(request);
        return jason;
    }
}

 

你可能感兴趣的:(分布式架构)