selector

selector

在这里插入图片描述

channel的四种事件

ServerSocketChannel有效事件为accept

socketChannel有效事件为connect、read、write

accept事件在ServerSocketChannel在接收到新的连接时触发.

read事件在socketChannel有可读信息时触发

write事件在socketChannel有可写信息时触发

connect事件在socketChannel连接建立成功时触发

accept事件

ServerSocketChannel 处理事件

server

package com.hello.netty;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;

@Slf4j
public class Server {
    public static void main(String[] args) throws IOException {
        // 1. 创建 selector 管理多个channel
        Selector selector = Selector.open();

        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);

        // 2. 建立 selector 和 channel 的联系(channel注册到selector)
        // SelectionKey 中包含了 selector 和 注册的 channel的信息.
        SelectionKey sscKey = ssc.register(selector, 0, null);
        // sscKey 只关注 accept事件
        sscKey.interestOps(SelectionKey.OP_ACCEPT);
        log.debug("register key: {}",sscKey);

        ssc.bind(new InetSocketAddress(8080));
        while(true){
            // 3. select方法,没有事件发生时,线程阻塞,有事件发生时继续运行.
            selector.select();
            // 4. 处理事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey key = iterator.next();
                log.debug("key: {}",key);

                ServerSocketChannel channel = (ServerSocketChannel)key.channel();
                SocketChannel sc = channel.accept();
                log.debug("SocketChannel: {}",sc);
            }
        }
    }
}
  • Selector selector = Selector.open();创建了selector 对象【selector

  • ServerSocketChannel ssc = ServerSocketChannel.open();创建了ServerSocketChannel 对象【channel

  • SelectionKey sscKey = ssc.register(selector, 0, null);将channel注册到selector上,返回值为SelectionKey,包含了该selector信息和注册上来的channel信息。selector中有个SelectionKey的集合属性,包含了注册到该selector的所有channel信息。

在这里插入图片描述

  • selector.select();是阻塞方法,如果注册到selector的所有channel都没有新事件发生,则线程处于阻塞状态。一旦存在有channel有新的事件发生,则继续向下执行。
  • selector.selectedKeys()返回一个set集合,是所有有新事件发生的channel集合。
  • channel.accept();处理ServerSocketChannel的事件。

client

package com.hello.netty;

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

public class Client {
    public static void main(String[] args) throws IOException {
        SocketChannel sc = SocketChannel.open();
        sc.connect(new InetSocketAddress("localhost",8080));
        System.out.println("waiting...");
    }
}

说明

先启动server,然后再启动两个client

  • SelectionKey地址一样

两个SelectionKey的地址sun.nio.ch.SelectionKeyImpl@2b71fc7e一样,因为两个连接都建立在同一个serverSocketChannel上。

  • SocketChannel地址不同

通过ServerSocketChannel#accept方法获取socketChannel,两个socketChannel的地址是不同的,是两个不同的socketChannel。

09:53:06.032 [main] DEBUG com.hello.netty.Server - register key: sun.nio.ch.SelectionKeyImpl@2b71fc7e
09:53:09.318 [main] DEBUG com.hello.netty.Server - key: sun.nio.ch.SelectionKeyImpl@2b71fc7e
09:53:09.318 [main] DEBUG com.hello.netty.Server - SocketChannel: java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:50530]
09:53:13.191 [main] DEBUG com.hello.netty.Server - key: sun.nio.ch.SelectionKeyImpl@2b71fc7e
09:53:13.191 [main] DEBUG com.hello.netty.Server - SocketChannel: java.nio.channels.SocketChannel[connected local=/127.0.0.1:8080 remote=/127.0.0.1:50536]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值