Java-NIO-Reactor-基础理解-案例

package com.example.demo;

import com.example.demo.nio.Acceptor;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
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;

@SpringBootTest
class DemoApplicationTests {

    @Test
    void contextLoads0() {
        try {
            Socket max = new Socket("localhost",9000);
            OutputStream outputStream = max.getOutputStream();
            outputStream.write("hello".getBytes());
            outputStream.write("你好".getBytes());
            max.close();
        }catch (Exception e){

        }

    }

    @Test
    void contextLoads1() {
        try {
             int MESSAGE_LENGTH = 1024; // 消息长度
            //是Java NIO库中的通道,用于监听和接受客户端连接
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //提供了非阻塞模式的支持,可以通过configureBlocking(false)方法设置为非阻塞模式。
            serverSocketChannel.configureBlocking(false);
            //绑定端口
            serverSocketChannel.bind(new InetSocketAddress(9000));
            //使用选择器(Selector)来管理多个通道,可以在一个线程中处理多个通道的连接请求。
            Selector selector = Selector.open();
            //通道注册到选择器中 返回令牌
            SelectionKey register = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            //令牌挂载对象
            register.attach(new Acceptor(selector,serverSocketChannel));

            while (true) {
                 //选择一组键,其对应通道已准备好进行I/O操作。
                //此方法执行阻塞选择操作。
                //只有在至少选择了一个通道、调用了该选择器的唤醒方法或中断了当前线程(以先到者为准)后,它才会返回。
                selector.select();
                //获取选择器中所有令牌
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                //遍历

                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    //是否已准备好接受新的套接字连接
                    if(key.isAcceptable()){
                        //获取令牌的挂载处理类 异步调用
                        Runnable runnable = (Runnable)key.attachment();
                        runnable.run();
                    }
                    if(key.isReadable()){
                        Runnable runnable = (Runnable)key.attachment();
                        runnable.run();

                    }
                    
                }
            }
        } catch (Exception e) {

        }
    }

}
package com.example.demo.nio;

import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class Acceptor implements Runnable{
    ServerSocketChannel serverSocketChannel;
    Selector selector;
    public Acceptor(Selector selector, ServerSocketChannel serverSocketChannel){
        this.selector=selector;
        this.serverSocketChannel=serverSocketChannel;
    }
    @Override
    public void run() {
        //
        try {
            //接受与此通道的套接字的连接
            System.out.println("进入Accept");
            SocketChannel socketChannel = serverSocketChannel.accept();
            System.out.println("有客户链接"+socketChannel.getRemoteAddress());
            socketChannel.configureBlocking(false);
            SelectionKey register = socketChannel.register(selector, SelectionKey.OP_READ);
            register.attach(new WorkHandler(socketChannel));
            System.out.println("离开Accept");
        }catch (Exception e){}
    }
}
package com.example.demo.nio;

import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;

public class WorkHandler implements Runnable {

    SocketChannel socketChannel;

    public WorkHandler( SocketChannel socketChannel){

        this.socketChannel=socketChannel;
    }
    @Override
    public void run() {
        try {
            System.out.println("进去WorkHandler");
            ByteBuffer byteBuffer =  ByteBuffer.allocate(1024);
            socketChannel.read(byteBuffer);
            String s = new String(byteBuffer.array(), StandardCharsets.UTF_8);
            System.out.println("消息:::::::::::::::::::"+s);
            //Thread.sleep(50000);
            //socketChannel.write(ByteBuffer.wrap("你的消息我收到了".getBytes()));
            System.out.println("离开WorkHandler");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值