您的位置:首页 > 编程语言 > Java开发

NIO selector多路复用器

2020-04-27 00:13 369 查看
  1. 基本流程与C语言一样:
      socket 设置非阻塞、bind绑定端口、listen监听连接、epoll_create、添加socket到epoll监听EPOLLIN、epoll_wait等待连接事件就绪的连接 accpet新连接。得到socket且设置非阻塞、添加到epoll监听EPOLLIN
    • 新的socket EPOLLIN事件就绪。读取数据。 如果程度是-1说明客户端关闭连接。JAVA中需要调用 channel.cancel()
    • 否则是正常数据输入
  2. selectionKey.remove()
public void testScannerServer() throws IOException {
System.out.println("服务端开启");
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

// 非阻塞
serverSocketChannel.configureBlocking(false);

serverSocketChannel.bind(new InetSocketAddress(8092));

Selector selector = Selector.open();

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (selector.select() > 0) {

// it won't clear the existing items 不会清空已经存在的 selectionKey。因此遍历处理一个后需要remove移除
Iterator<SelectionKey> it = selector.selectedKeys().iterator();

while (it.hasNext()) {
SelectionKey key = it.next();
// 为什么要remove?因为 select 就绪队列,如果不移除就会一直存在
// https://stackoverflow.com/questions/7132057/why-the-key-should-be-removed-in-selector-selectedkeys-iterator-in-java-ni
it.remove();
if (!key.isValid()) {
System.out.println("连接不可用");
} else if (key.isAcceptable()) {
// 新连接
System.out.println("服务端接受到新连接");
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false); // 非阻塞
socketChannel.register(selector, SelectionKey.OP_READ); // 注册可读事件
} else if (key.isReadable()) {
// 有客户端发送数据
SocketChannel socketChannel = (SocketChannel) key.channel();
// 开始读取数据
System.out.println(new Date().toString());
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

if (socketChannel.read(byteBuffer) == -1) {
// -1 说明客户端关闭了写或者直接close
System.out.println("客户端关闭连接");
// socketChannel.close(); // 其实不需要调用,因为客户端已经关闭, 为了程序稳健性可以开启
key.cancel(); // 取消注册
} else {
byteBuffer.flip();
System.out.println(new String(byteBuffer.array(), 0, byteBuffer.limit()));
byteBuffer.clear();
}
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  epoll java bind