Channel 通道
通道表示到实体(如硬件设备、文件、网络套接字或程序组件)的开放连接,该实体能够执行一个或多个不同的I/O操作,例如读取或写入
FileChannel
- 用于读取、写入、映射和操作文件的通道
- 文件通道是连接到文件的
SeekableByteChannel
。它在其文件中有一个当前的 position ,可以是查询 position ,也可以是修改的 position(long) 。文件本身包含一个可变长度的字节序列,可以读取和写入,并且可以查询当前的 size 。当写入的字节超过当前大小时,文件大小会增加;当文件 truncated 时,文件大小会减小。文件还可能具有一些关联的元数据,例如访问权限、内容类型和上次修改时间;此类不定义元数据访问的方法。
FileChannel的类继承关系:
- FileChannel的读写分离体现了接口的隔离原则
- FileChannel中的read函数根据 直接或非直接 ByteBuffer读取到堆缓冲区或者直接返回buffer缓冲区
SocketChannel
- 网络套接字Socket和上面文件是一样的,在Linux上都抽象成了 文件描述符fd
- SocketChannel面向流的连接套接字的可选通道
- 通过调用此类的
open
方法创建套接字通道。无法为任意的、预先存在的套接字创建通道。新创建的套接字通道已打开,但尚未连接。试图在未连接的通道上调用I/O操作将导致引发NotYetConnectedException
。套接字通道可以通过调用其connect
方法进行连接;一旦连接,套接字通道将保持连接,直到关闭。套接字通道是否连接可以通过调用其isConnected
方法来确定 - SocketChannel支持 无阻塞连接
SocketChannel的类继承关系:
Selector
- Selector是SelectableChannel对象的多路复用选择器
- 可以通过调用此类的
open
方法来创建选择器,该方法将使用系统默认的java.nio.channels.spi.SelectorProvider
选择器来创建新的选择器。还可以通过调用自定义选择器java.nio.channels.spi.SelectorProvider.openSelector
方法来创建选择器。选择器保持打开状态,直到通过其close
方法关闭为止
ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.register(selector, SelectionKey.OP_ACCEPT);
public class Server { public static void main(String[] args) throws IOException { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress("127.0.0.1", 8888)); ssc.configureBlocking(false); System.out.println("server started, listening on :" + ssc.getLocalAddress()); Selector selector = Selector.open(); ssc.register(selector, SelectionKey.OP_ACCEPT); while(true) { selector.select(); Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> it = keys.iterator(); while(it.hasNext()) { SelectionKey key = it.next(); it.remove(); handle(key); } } } private static void handle(SelectionKey key) { if(key.isAcceptable()) { try { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); //new Client // //String hostIP = ((InetSocketAddress)sc.getRemoteAddress()).getHostString(); /* log.info("client " + hostIP + " trying to connect"); for(int i=0; i<clients.size(); i++) { String clientHostIP = clients.get(i).clientAddress.getHostString(); if(hostIP.equals(clientHostIP)) { log.info("this client has already connected! is he alvie " + clients.get(i).live); sc.close(); return; } }*/ sc.register(key.selector(), SelectionKey.OP_READ ); } catch (IOException e) { e.printStackTrace(); } finally { } } else if (key.isReadable()) { //flip SocketChannel sc = null; try { sc = (SocketChannel)key.channel(); ByteBuffer buffer = ByteBuffer.allocate(512); buffer.clear(); int len = sc.read(buffer); if(len != -1) { System.out.println(new String(buffer.array(), 0, len)); } ByteBuffer bufferToWrite = ByteBuffer.wrap("HelloClient".getBytes()); sc.write(bufferToWrite); } catch (IOException e) { e.printStackTrace(); } finally { if(sc != null) { try { sc.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
原文
https://segmentfault.com/a/1190000022097365
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Netty源码01-Java的NIO(二)