Java复习之知识点整理(三十二)---Selectors 挑选器,NIO实现Socket编程

一、Selectors 挑选器
---------------------------------------------------------------------
    1.Selectors:用于挑选通道感兴趣的方法是否发生,是selectkey的集合
    2.SelectionKey:表示通道和selector之间的一种绑定,是对通道的一种封装
    3.Selector.open();          //打开一个挑选器
    4.SelectionKey register(Selector sel ,int ops);        //(通道打点调用)给通道注册挑选器,并指定感兴趣的事件,返回唯一标识
    -- ops: Selectionkey.OP_READ
    -- ops: Selectionkey.OP_WRITE
    -- ops: Selectionkey.OP_CONNECT
    -- ops: Selectionkey.OP_ACCEPT
    5.selector.select();        //开始挑选感兴趣的事件,阻塞的,返回值int 表示状态发生变化的通道数量
    6.添加到selector中的通道必须是非阻塞的
    7.挑选器是一个集合,里面可以保存很多的通道。采用轮询机制来查看这些通道是否发生了自己感兴趣的事件
    8.可以通过 key.cancel() 删除指定sekey的通道

二、使用SocketChannel实现socket编程
-----------------------------------------------------------------------------
1.控制台输入语句,发送给服务器,并且得到服务器的回执

---------------------------------------------------------------------------------------------
------------------------------------1.Server端---------------------------------------------
---------------------------------------------------------------------------------------------
/**
 * NIO:NioServer
 */
public class NioServer {
    
    public static void main(String[] args) {
        
        try {
            //1.打开channel
            ServerSocketChannel ssc = ServerSocketChannel.open();
            //2.绑定ip
            InetSocketAddress local = new InetSocketAddress("0.0.0.0", 8888);
            ssc.bind(local);
            //3.设置非阻塞模式
            ssc.configureBlocking(false);
            //4.打开挑选器
            Selector st = Selector.open();
            //5.给channel注册挑选器,并注册感兴趣事件accept
            ssc.register(st, SelectionKey.OP_ACCEPT);
            //6.开始挑选
            while(true)
            {
                try {
                    //7.阻塞的,如果没有发生感兴趣的事件,就一直等待
                    st.select();                        
                } catch (Exception e) {
                    // TODO: handle exception
                }                
                //8.获取发生变化的key(key中封装有channel)
                Set<SelectionKey> set = st.selectedKeys();
                for (SelectionKey key : set) {
                    
                    try {
                        
                        //如果是accept,说明是服务器
                        if(key.isAcceptable())
                        {
                            //9.找到变化的channel
                            ServerSocketChannel scc1 = (ServerSocketChannel) key.channel();
                            //10.获取用于与客户端通信的SocketChannel
                            SocketChannel sc1 = scc1.accept();
                            sc1.configureBlocking(false);
                            //11.将得到的SocketChannel注册到挑选器中,设置感兴趣的事件
                            sc1.register(st, SelectionKey.OP_CONNECT |SelectionKey.OP_READ | SelectionKey.OP_WRITE );                        
                        }
                        
                        //如果是可读的,那就读
                        if(key.isReadable())
                        {                        
                            SocketChannel sc1 = (SocketChannel) key.channel();
                            ByteBuffer dst = ByteBuffer.allocate(1024);
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            while(sc1.read(dst) != 0)
                            {
                                dst.flip();
                                baos.write(dst.array(), 0, dst.limit());
                                dst.clear();
                                String str = new String(baos.toByteArray());
                                System.out.println("客户端说: " + str);
                                
                                dst = ByteBuffer.allocate(1024);
                                str = new String("hello:" + str);
                                dst.put(str.getBytes());
                                dst.flip();
                                sc1.write(dst);
                                dst.clear();    
                            }
                            baos.close();
                        }
                        
                        
                    } catch (Exception e) {
                        e.printStackTrace();
                        //如果出现了错误,回收掉key
                        key.cancel();                        
                    }
                }
                set.clear();            
            }
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }        
    }
}


---------------------------------------------------------------------------------------------
------------------------------------2.Client端---------------------------------------------
---------------------------------------------------------------------------------------------
/**
 * Nio : Client
 */
public class NioClient {
    public static void main(String[] args) {
        
        try {
            //打开socketChannel
            SocketChannel sc = SocketChannel.open();
            
            InetSocketAddress ip = new InetSocketAddress("localhost", 8888);
            //要在设定非阻塞之前进行连接,因为要确保连接已经成功!
            sc.connect(ip);
            
            sc.configureBlocking(false);
    
            
            //打开selector
            Selector st = Selector.open();
            sc.register(st, SelectionKey.OP_READ);
            
            //给服务器发消息
            new sender(sc).start();
            
            //
            ByteBuffer dst = ByteBuffer.allocate(1024) ;
            while(true)
            {
                st.select();    
                while(sc.read(dst) != 0)
                {
                    dst.flip();
                    String str = new String(dst.array(),0,dst.limit());
                    System.out.println("服务器回执:" + str);
                    dst.clear();
                }            
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }
}


---------------------------------------------------------------------------------------------
------------------------------------3. 客户端消息发送器---------------------------------
---------------------------------------------------------------------------------------------
/**
 * 客户端消息发送器
 */
public class sender extends Thread{
    
    private SocketChannel sc = null;
    
    public sender(SocketChannel sc) {
        this.sc = sc;
    }

    @Override
    public void run() {
        
        try {
            
            ByteBuffer src = ByteBuffer.allocate(1024);
            
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String str = null;
            byte [] buf = null;
            while((str = br.readLine()) != null)
            {
                src = ByteBuffer.allocate(1024);
                buf = str.getBytes();
                src.put(buf);
                src.flip();
                sc.write(src);
                src.clear();                
            }
        
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}

猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/81332933
今日推荐