NIO-02

2020-08-17  本文已影响0人  平头哥2

server


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
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 Exception {
        // 1. 获取 ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 2. 获取 Selector 对象
        Selector selector = Selector.open();

        // 3. 绑定一个 ip 和 端口 6666, 在服务器端监听
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));

        // 4. 设置为非阻塞
        serverSocketChannel.configureBlocking(false);

        // 5. 把 serverSocketChannel 注册到 selector 关心, 事件为 OP_ACCEPT
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 6. 循环等待客户端链接
        while (true) {

            // eg: 这里我们等待1秒,如果没有事件发生,就返回

            if (selector.select(1000) == 0) {// eg: 没有事件发生
                System.out.println("服务器等待了1秒, 无链接");
                continue;
            }

            // eg: 如果返回的 大于0
            // eg: 该集合是表示有 事件发生的集合
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            // eg: 通过 selectedKeys 可以反向获取 channel

            Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey selectionKey = keyIterator.next();
                if (selectionKey.isAcceptable()) {
                    // accept() 是阻塞的,但是这里不会阻塞
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    // eg: 将 socketChannel 注册到 selector 上, 关注只读事件,关联一个 ByteBuffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }

                if (selectionKey.isReadable()) {
                    // eg: 通过key 反向获取channel
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    ByteBuffer attachment = (ByteBuffer) selectionKey.attachment();
                    int read = channel.read(attachment);
                    
                    System.out.println("客户端发送来的数据:"+new String(attachment.array(),0, attachment.position()));
                    
                }
                // eg: 手动从集合中移除 selectionKey, 防止重复提交
                // selectedKeys.remove(selectionKey); 并发修改异常
                keyIterator.remove();
            }
        }

    }

}

client

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NIOClient {

    public static void main(String[] args) throws Exception {
        // 1: 客户端通道
        SocketChannel socketChannel = SocketChannel.open();
        
        //2. 设置为非阻塞
        socketChannel.configureBlocking(false);
        
        //3. 链接服务器
        InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost", 6666);
        
        //4. 链接
        if(!socketChannel.connect(inetSocketAddress)) {
            while (! socketChannel.finishConnect()) {
                System.out.println("客户端链接需要时间...");
                
            }
        }
        //4.1 如果链接成功,发送数据
        String content = "helloworld";
        ByteBuffer buffer = ByteBuffer.wrap(content.getBytes());
        
        socketChannel.write(buffer);
        
        //System.in.read();
        
    }
}
上一篇下一篇

猜你喜欢

热点阅读