美文网首页
NIO入门示例

NIO入门示例

作者: touch_The_Sky | 来源:发表于2020-04-24 16:06 被阅读0次

    server端

    package com.example.demo.socket;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    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;
    
    public class NioServer {
        public static void main(String[] args) throws IOException {
            server(8888);
        }
        public static void server(int port) throws IOException {
            //1、打开服务器套接字通道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //2、设定为非阻塞、调整此通道的阻塞模式。
            serverSocketChannel.configureBlocking(false);
            //3、创建一个与此通道关联的服务器套接字。
            ServerSocket serverSocket = serverSocketChannel.socket();
            //4、此类实现 ip 套接字地址 (ip 地址 + 端口号)
            InetSocketAddress address = new InetSocketAddress(port);
            //5、将服务器绑定到选定的套接字地址
            serverSocket.bind(address);
    
            //6、打开Selector来处理Channel
            Selector selector = Selector.open();
            //7、将ServerSocket注册到Selector已接受连接,注册会判断是否为非阻塞模式
            SelectionKey     selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            ByteBuffer       readBuff     = ByteBuffer.allocate(1024);
            final ByteBuffer msg          = ByteBuffer.wrap("Hi!".getBytes());
            while (true){
                try {
                    //等到需要处理的新事件:阻塞将一直持续到下一个传入事件
                    selector.select();
                }catch (IOException e){
                    e.printStackTrace();
                    break;
                }
                //获取所有接收事件的SelectionKey实例
                Set<SelectionKey>      readykeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator  = readykeys.iterator();
                while(iterator.hasNext()){
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    try {
                        //检查事件是否是一个新的已经就绪可以被接受的连接
                        if (key.isAcceptable()){
                            //channel:返回为其创建此键的通道。 即使在取消密钥后, 此方法仍将继续返回通道。
                            ServerSocketChannel server = (ServerSocketChannel)key.channel();
                            //可选择的通道, 用于面向流的连接插槽。
                            SocketChannel client = server.accept();
                            //设定为非阻塞
                            client.configureBlocking(false);
                            //接受客户端,并将它注册到选择器,并添加附件
                            client.register(selector,SelectionKey.OP_WRITE | SelectionKey.OP_READ,msg.duplicate());
                            System.out.println("Accepted connection from " + client);
                        }
                        //检查套接字是否已经准备好读数据
                        if (key.isReadable()){
                            SocketChannel client = (SocketChannel)key.channel();
                            readBuff.clear();
                            int read = client.read(readBuff);
                            readBuff.flip();
                            System.out.println("server收到:  "+new String(readBuff.array(),0,read));
                            //将此键的兴趣集设置为给定的值。 OP_WRITE
                            key.interestOps(SelectionKey.OP_WRITE);
                        }
                        //检查套接字是否已经准备好写数据
                        if (key.isWritable()){
                            SocketChannel client = (SocketChannel)key.channel();
                            //attachment : 检索当前附件
                            ByteBuffer buffer = (ByteBuffer)key.attachment();
                            buffer.rewind();
                            client.write(buffer);
                            //将此键的兴趣集设置为给定的值。 OP_READ
                            key.interestOps(SelectionKey.OP_READ);
                        }
                    }catch (IOException e){
                        //发生异常从selector取消注册,防止一直报错
                        key.cancel();
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    

    client端

    package com.example.demo.socket;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    
    public class WebClient {
       public static void main(String[] args) throws IOException {
           try {
               SocketChannel socketChannel = SocketChannel.open();
               socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));
    
               ByteBuffer writeBuffer = ByteBuffer.allocate(32);
               ByteBuffer readBuffer = ByteBuffer.allocate(32);
    
               writeBuffer.put("helloWebClient ".getBytes());
               writeBuffer.flip();
               while (true){
                   writeBuffer.rewind();
                   socketChannel.write(writeBuffer);
                   readBuffer.clear();
                   int read = socketChannel.read(readBuffer);
                   readBuffer.flip();
                   System.out.println("client收到:  "+new String(readBuffer.array(),0,read));
                   Thread.sleep(2000L);
                   //关闭
                   //socketChannel.close();
               }
           }catch (IOException e){
               e.printStackTrace();
           } catch (InterruptedException e) {
    
    
           }
       }
    }
    

    相关文章

      网友评论

          本文标题:NIO入门示例

          本文链接:https://www.haomeiwen.com/subject/ookfwhtx.html