FEIQQ学习总结--NIO

zhy

发布于 2020.02.13 19:25 阅读 2420 评论 0

    看完FEIQQ--Netty版本的源码后,接下来用NIO来实现程序的功能。

 

软件原理:

 

    程序主要运用了mysql数据库技术进行数据处理,NIO技术实现客户端与服务器交互。NIO是非阻塞异步IO,是基于缓存区的IO。

 

实现思路:

 

   程序在启动时会调用Server类和Client类的start方法,start方法包含了NIO的使用,包括以下几步:

1. 首先SocketChannel.open()方法打开信息通道

2. 调用configureBlocking方法,设置非阻塞模式。

3. 调用connect()或bind方法绑定ip。

4. 调用Selector.open()方法打开多路复用器。

5. 利用register方法把通道注册到多路复用器上。

        6.将Selector.select()放入while(true)循环中,一直监听,对获取的SelectionKey进行处理。

 

结构示意图:

 

 

代码实现:

        sc=SocketChannel.open();//打开信道
        sc.configureBlocking(false);//设置为非阻塞模式
        sc.connect(new InetSocketAddress(Constants.SERVER_IP,Constants.SERVER_PORT));//连接服务端
        
        selector = Selector.open();//必须打开
        //将当前客户端注册到多路复用器上
        sc.register(selector, SelectionKey.OP_CONNECT);

        new Thread(){
            public void run(){
                while(true){//一直循环
                    try {
                        selector.select();//多路复用器开始监听
                        //获取已经注册在多了复用器上的key通道集
                        Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
                        //遍历
                        while (keys.hasNext()) {
                            SelectionKey key = keys.next();//获取key
                            //如果是有效的
                            if(key.isValid()){
                                SocketChannel socket=(SocketChannel) key.channel();
                                if(key.isConnectable()){
                                    if(socket.finishConnect()){
                                        connect(key);
                                        System.out.println("客户端连接");
                                    }

                                }
                                // 如果为可读状态,读取服务端返回的数据
                                if(key.isReadable()){
                                    read(key);
                                }
                            }
                            //从容器中移除处理过的key
                            keys.remove();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

 

实现效果:

 

 

 

心得体会:  

 

     NIO是基于通道(Channel)和缓冲区(Buffer)的流,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中,是异步,非阻塞的IO,NIO提供的Selector可以使一个线程管理多个通道,有效节省了线程但是NIO的编码复杂,需要处理半包和粘包问题。
     但通过上面的步骤能看出,与使用Netty相比,Nio的操作步骤更多,更复杂,Nio的功能也比较少。当然,Netty是基于NIO的网路框架,Netty的功能用NIO也可以实现,不过需要自己实现。