首页 / NETTY / Netty5概述-原创
Netty5概述-原创
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Netty5概述-原创,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4314字,纯文字阅读大概需要7分钟。
内容图文
private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { final NioUnsafe unsafe = ch.unsafe(); if (!k.isValid()) { // close the channel if the key is not valid anymore unsafe.close(unsafe.voidPromise()); return; } try { //得到当前的key关注的事件 int readyOps = k.readyOps(); // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead // to a spin loop //一个刚刚创建的NioServersocketChannel感兴趣的事件是0。 if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {//可以读取操作 --对于serverSocket来说就是acceptor事件、对于socketChannel来说就是read事件 //INFO: channel类型为io.netty.channel.socket.nio.NioSocketChannel unsafe类型为io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe Object obj = k.attachment();//得到NioServerSocketChannel或者NioSocketChannel if(obj instanceof NioServerSocketChannel){ System.out.println(obj.getClass().getName()+ " 开始接收连接"); }else{ System.out.println(obj.getClass().getName()+ " 开始接收字节"); } //不同的socketChannel对于那个的unsafe是不同的。例如Server端的是messageUnsafe 而 clinet端是byteUnsafe unsafe.read();//对于接受链接或者read兴趣都会添加进入read操作调用serverSocket->NioMessageUnsafe if (!ch.isOpen()) { // Connection already closed - no need to handle write. return; } } if ((readyOps & SelectionKey.OP_WRITE) != 0) {//对于半包消息进行输出操作 // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write ch.unsafe().forceFlush(); } if ((readyOps & SelectionKey.OP_CONNECT) != 0) { // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking // See https://github.com/netty/netty/issues/924 int ops = k.interestOps(); ops &= ~SelectionKey.OP_CONNECT; k.interestOps(ops); unsafe.finishConnect(); } } catch (CancelledKeyException e) { unsafe.close(unsafe.voidPromise()); } }
这里我们以连接的建立(NioMessageUnsafe)为线索进行讲解。后续会有基于byte的unsafe进行讲解的(Unsafe不知道为啥要这么叫,本人也感到挺费解的,不过现在看来感觉就是一个工具对象。不要从名称上惧怕它)。下面来看NioMessageUnsafe的read方法进行讲解。直接讲代码(后面也会有图形讲解,方便大家理解):
@Override public void read() { assert eventLoop().inEventLoop(); if (!config().isAutoRead()) { removeReadOp(); } final ChannelConfig config = config(); //得到本次方法调用可以接收的连接数目 final int maxMessagesPerRead = config.getMaxMessagesPerRead(); final boolean autoRead = config.isAutoRead(); final ChannelPipeline pipeline = pipeline(); boolean closed = false; Throwable exception = null; try { for (;;) { //将msg从读取出来(SocketChannel-(common msg); serverSocketChannel(socketChannel msg)) int localRead = doReadMessages(readBuf);//readBuf仅仅是在本方法中起到缓冲统计的作用。不要多想哦!! if (localRead == 0) { break; } if (localRead < 0) { closed = true; break; } //每次读取的message的个数--- if (readBuf.size() >= maxMessagesPerRead | !autoRead) { break;//避免一次性创建过多的连接个数 } } } catch (Throwable t) { exception = t; } int size = readBuf.size(); for (int i = 0; i < size; i ++) { //对于server端来说,第一个handler为io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor ////针对所有的channel都会执行一个read操作;对于ServerSocketChannel ServerSocketChannel对应的pipeline的fireChannelRead方法 //因为ServerSocketChannel的pipeline的第一个handler pipeline.fireChannelRead(readBuf.get(i)); } readBuf.clear();//清空到的连接缓存 pipeline.fireChannelReadComplete(); if (exception != null) { if (exception instanceof IOException) { // ServerChannel should not be closed even on IOException because it can often continue // accepting incoming connections. (e.g. too many open files) closed = !(AbstractNioMessageChannel.this instanceof ServerChannel); } pipeline.fireExceptionCaught(exception); } if (closed) { if (isOpen()) { close(voidPromise()); } } } }
下面让我们来看看上面这段代码中提到的
int localRead = doReadMessages(readBuf);//doReadMessages是个抽象方法
上代码:
@Override
protected int doReadMessages(List<Object> buf) throws Exception {//对于NioServerSocketChannel,它的读取操作,就是接受客户端的链接和创建NioSocketChannel
SocketChannel ch = javaChannel().accept();//得到java远程的socketChannel对象。不要认为此处会阻塞,不会的因为connec事件发生了。所以会立即返回
try {
if (ch != null) {
//进行包装,包装成netty的NioSocketChannel对象-将所有绑定socketChannel的处理线程
buf.add(new NioSocketChannel(this, childEventLoopGroup().next(), ch));
return 1;//每次仅仅处理一个,并且将得到连接对象放入到buf列表对象中进行保存
}
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted socket.", t);
try {
ch.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
}
return 0;
}
原文:http://my.oschina.net/hotbain/blog/420941
内容总结
以上是互联网集市为您收集整理的Netty5概述-原创全部内容,希望文章能够帮你解决Netty5概述-原创所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。