欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

javaNIO原理的一个基本demo

程序员文章站 2022-06-02 23:53:59
...


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

/**
 *
 */
public class NioClientTest {

    public static void main(String[] args) throws IOException {

        SocketChannel socketChannel = SocketChannel.open();
        //设置非阻塞
        socketChannel.configureBlocking(false);

        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",
                8000);

        //判断连接
        if(!socketChannel.connect(inetSocketAddress)){
            //链接失败
            while (!socketChannel.finishConnect()){
                System.out.println("客户端非阻塞,干点其他的事情吧");
            }
        }
        //链接成功发送数据
        String str="hello world";
        //根据字节数组大小创建一个buffer大小
        ByteBuffer byteBuffer=ByteBuffer.wrap(str.getBytes());
        //将buffer中的数据写入到channel中
        socketChannel.write(byteBuffer);
        System.in.read();

    }

}

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;

/**
 * 1、客户端连接到服务端的时候ServerSocketChannel 获取连接生成SocketChannel
 * 2、服务端创建一个Selector.open,
 * 3、刚才生成的socketChannel 注册到register到selector中
 * 4、注册后返回一个SelectedKey  由selector管理
 * 5 、selector 进行监听 select,selectNow 返回有事件发生的socketchannel个数
 *  6、获取selector所管理的有事件发生的selectedKeys 集合,然后循环遍历所有的事件 通过selectedKey反向获取SocketChannel
 *  7、通过获取的socketchannel完成对应事件的处理
 *
 */
public class NIOServerTest {

    public static void main(String[] args) throws IOException {
        //创建server
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //绑定一个端口
        serverSocketChannel.socket().bind(new InetSocketAddress(8000));

        //创建一个selector
        Selector selector = Selector.open();
        //设置非阻塞
        serverSocketChannel.configureBlocking(false);
        //将ServerSocketChannel 注册到选择器中 关心Accept事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        //循环等待客户端连接
        while (true){
            //阻塞等待关心的channel事件发生
            int select = selector.select();

            //如果有事件发生select>0 获取到相关事件的集合
            Iterator<SelectionKey> iterator = selector.selectedKeys()
                    .iterator();
            while (iterator.hasNext()){
                //获取发生事件的key
                SelectionKey selectionKey=iterator.next();
                //如果是连接请求事件
                if(selectionKey.isAcceptable()&&selectionKey.isValid()){
                    ServerSocketChannel serverSocketChannelAccept=(ServerSocketChannel)selectionKey.channel();
                    //给客户端生成一个SocketChannel  非阻塞
                    SocketChannel socketChannel = serverSocketChannelAccept.accept();
                    System.out.println("客户端链接成功 生成一个sockeychannel"+socketChannel.hashCode());
                    //设置客户端为非阻塞的
                    socketChannel.configureBlocking(false);
                    //将与客户端连接的socketChannel也注册到selector中 同时给 Channel关联一个buffer
                    socketChannel.register(selector,SelectionKey.OP_READ,
                            ByteBuffer.allocate(1024));
                }else if(selectionKey.isReadable()&&selectionKey.isValid()){
                    //通过key反向获取对应的channel进行读取
                    SocketChannel readSocketChannel=(SocketChannel) selectionKey.channel();
                    //获取该channel关联的buffer
                    ByteBuffer buffer=(ByteBuffer) selectionKey.attachment();
                    readSocketChannel.read(buffer);
                    System.out.println("客户端发送的数据:"+new String(buffer.array()));
                }
                //手动将selectionKey从集合中移除 防止重复操作
                iterator.remove();
            }
        }
    }
}

相关标签: java 网络