关于Seletor中的Set<SelectionKey>需要remove的问题

package com.leetcode.random.difficulty;
import org.junit.Test;
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;


public class Design {
    public static void main(String args[]) throws IOException {
        System.out.println("开始输入");
        Scanner scan = new Scanner(System.in);
        SocketChannel channel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8888));
        channel.configureBlocking(false);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        while (scan.hasNext()) {
            String str = scan.next();
            buffer.put((new Date().toString()+"——>"+str).getBytes());
            buffer.flip();
            channel.write(buffer);
            buffer.clear();
        }
        System.out.println("jieshu");
    }

    @Test
    public  void serverdemo() throws IOException {
            ServerSocketChannel channel = ServerSocketChannel.open();
            channel.socket().bind(new InetSocketAddress(8888));
            channel.configureBlocking(false);
            ByteBuffer b = ByteBuffer.allocate(10);
            Selector s = Selector.open();
            channel.register(s,SelectionKey.OP_ACCEPT);
            while (s.select() > 0) {
                Set<SelectionKey> se = s.selectedKeys();
                for (SelectionKey next: se) {
                    se.remove(next);
                    if (next.isAcceptable()) {
                        SocketChannel sc = channel.accept();
                        sc.configureBlocking(false);
                        sc.register(s, SelectionKey.OP_READ);
                    }
                    if (next.isReadable()) {
                        SocketChannel sc = (SocketChannel) next.channel();   
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int length = 0;
                        while ((length = sc.read(byteBuffer))>0) {
                            byteBuffer.flip();
                            System.out.println(new String(byteBuffer.array(), 0, length));
                            byteBuffer.clear();
                        }
                    }
                }
            }
        }
    }


代码功能:main方法不断通过控制台输入请求socket连接,发送信息;服务端打印信息。

服务端代码注意:

Set<SelectionKey>必须把遍历过的对象remove,否则下次再拿到用过的key,得到的SocketChannel sc = channel.accept()是null。因此在Selector中注册事件激活以后,如果不手动移除key,他会一直存在。

学习的时候有这么一句话:“SocketChannel可以重用,但socket不能重用!

我想这句话的意思是:在Seletor中就是指“选择键Key”不能重复使用,用完要移除,否则下次遍历再拿到旧Key,但里面已经没有Socket连接了(给取走过.getChannel),因此再调用getChannel返回null。此时会报java.lang.NullPointerException: Cannot invoke "java.nio.channels.SocketChannel.configureBlocking(boolean)" because "sc" is null

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值