Cobar启动完成,监听特定端口。整个认证的流程图:

NIOAcceptor类继承自Thread类,该类的对象会以线程的方式运行,进行连接的监听。
NIOAcceptor启动的初始化过程如下:
1 、打开一个selector,获取一个ServerSocketChannel对象,对该对象的socket绑定特定的监听端口,并设置该channel为非阻塞模式,然后想selector注册该channel,绑定感兴趣的事件位OP_ACCEPT。
| 01 |
public NIOAcceptor(String name, int port, FrontendConnectionFactory factory) throws IOException { |
| 04 |
this.selector = Selector.open(); |
| 05 |
this.serverChannel = ServerSocketChannel.open(); |
| 07 |
this.serverChannel.socket().bind(new InetSocketAddress(port)); |
| 08 |
this.serverChannel.configureBlocking(false); |
| 09 |
this.serverChannel.register(selector, SelectionKey.OP_ACCEPT); |
| 10 |
this.factory = factory; |
2、 然后会启动该线程,线程的run函数如下:
| 02 |
final Selector selector = this.selector; |
| 07 |
selector.select(1000L); |
| 08 |
Set keys = selector.selectedKeys(); |
| 10 |
for (SelectionKey key : keys) { |
| 11 |
if (key.isValid() && key.isAcceptable()) { |
| 21 |
} catch (Throwable e) { |
| 22 |
LOGGER.warn(getName(), e); |
3 、 该线程会一直循环监听想该selector注册过的server channel所感兴趣的事件(OP_ACCEPT),当有新的连接请求时,selector就会返回,keys就是请求连接的所有的包含channel的key集合。
SelectionKey有如下属性:
- interest集合(使用&操作SelectionKey.OP_ACCEPT和key.interestOps())
- ready集合(key.readyOps(),可以使用&操作检测该集合,也可以使用is方法)
- Channel(key.channel())
- Selector(key.selector())
- 附加对象(key.attach(obj) Object obj = key.attachment())
4、 然后遍历该集合,如果集合中的key没有被cancel,并且这个key的channel已经做好接受一个新的socket连接的准备,则接受该连接。
accept()的具体代码如下:
| 01 |
private void accept() { |
| 02 |
SocketChannel channel = null; |
| 05 |
channel = serverChannel.accept(); |
| 07 |
channel.configureBlocking(false); |
| 12 |
FrontendConnection c = factory.make(channel); |
| 15 |
c.setId(ID_GENERATOR.getId()); |
| 17 |
NIOProcessor processor = nextProcessor(); |
| 18 |
c.setProcessor(processor); |
| 21 |
processor.postRegister(c); |
| 22 |
} catch (Throwable e) { |
| 23 |
closeChannel(channel); |
| 24 |
LOGGER.warn(getName(), e); |
首先从serverchannel中accept后会返回一个socketchannel对象,然后设置该socket channel属性位非阻塞模式,然后将channel交给ServerConnectionFactory工厂,会产生一个ServerConnection对象。

FrontendConnectionFactory是一个抽象类,其中的getConnection方法是抽象方法,有具体子类连接工厂来实现。FrontendConnectionFactory的make方法对channel中的socket进行属性设置(接收和发送的缓冲区大小、延时、KeepAlive等),然后调用具体调用具体子类(ServerConnectionFactory)的getConnection来返回一个ServerConne