java nio socket 原理_深入浅出NIO Socket实现机制

本文深入介绍了Java NIO中的Selector和Socket实现原理,包括Selector如何管理多个SocketChannel,以及其在服务端的使用示例。通过Selector,一个线程可以高效地处理多个通道的连接、读写事件。文章还探讨了Selector的内部实现,以及与epoll的关系,展示了Java NIO在非阻塞I/O和高性能网络编程中的应用。
摘要由CSDN通过智能技术生成

前言

Java NIO 由以下几个核心部分组成:

Buffer

Channel

Selector

以前基于net包进行socket编程时,accept方法会一直阻塞,直到有客户端请求的到来,并返回socket进行相应的处理。整个过程是流水线的,处理完一个请求,才能去获取并处理后面的请求;当然我们可以把获取socket和处理socket的过程分开,一个线程负责accept,线程池负责处理请求。

NIO为我们提供了更好的解决方案,采用选择器(Selector)找出已经准备好读写的socket,并按顺序处理,基于通道(Channel)和缓冲区(Buffer)来传输和保存数据。

Buffer和Channel已经介绍过深入浅出NIO Channel和Buffer,本文主要介绍NIO的Selector和Socket的实践以及实现原理。

Selector是什么?

在养鸡场,有这一个人,每天的工作就是不停检查几个特殊的鸡笼,如果有鸡进来,有鸡出去,有鸡生蛋,有鸡生病等等,就把相应的情况记录下来。这样,如果负责人想知道鸡场情况,只需要到那个人查询即可,当然前提是,负责得让那个人知道需要记录哪些情况。

Selector的作用相当这个人的工作,每个鸡笼相当于一个SocketChannel,单个线程通过Selector可以管理多个SocketChannel。

86c913d2e3d3c93e245d94d669321f4f.png

A Thread uses a Selector to handle 3 Channels

为了实现Selector管理多个SocketChannel,必须将多个具体的SocketChannel对象注册到Selector对象,并声明需要监听的事件,目前有4种类型的事件:

connect:客户端连接服务端事件,对应值为SelectionKey.OP_CONNECT(8)

accept:服务端接收客户端连接事件,对应值为SelectionKey.OP_ACCEPT(16)

read:读事件,对应值为SelectionKey.OP_READ(1)

write:写事件,对应值为SelectionKey.OP_WRITE(4)

当SocketChannel有对应的事件发生时,Selector能够觉察到并进行相应的处理。

为了更好地理解NIO Socket,先来看一段服务端的示例代码

ServerSocketChannel serverChannel =ServerSocketChannel.open();

serverChannel.configureBlocking(false);

serverChannel.socket().bind(newInetSocketAddress(port));

Selector selector=Selector.open();

serverChannel.register(selector, SelectionKey.OP_ACCEPT);while(true){int n =selector.select();if (n == 0) continue;

Iterator ite= this.selector.selectedKeys().iterator();while(ite.hasNext()){

SelectionKey key=(SelectionKey)ite.next();if(key.isAcceptable()){

SocketChannel clntChan=((ServerSocketChannel) key.channel()).accept();

clntChan.configureBlocking(false);//将选择器注册到连接到的客户端信道,//并指定该信道key值的属性为OP_READ,//同时为该信道指定关联的附件

clntChan.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufSize));

}if(key.isReadable()){

handleRead(key);

}if (key.isWritable() &&key.isValid()){

handleWrite(key);

}if(key.isConnectable()){

System.out.println("isConnectable = true");

}

ite.remove();

}

}

服务端连接过程

1、创建ServerSocketChannel实例serverSocketChannel,并bind到指定端口。

2、创建Selector实例selector;

3、将serverSo

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值