NIO入门笔记01

来源:互联网 发布:python的数据类型 编辑:程序博客网 时间:2024/06/05 09:36

传统的I/O与NIO区别

传统的I/O(同步阻塞的IO):

使用传统的I/O程序读取文件内容, 并写入到另一个文件(或Socket), 如下程序:

File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);
会有较大的性能开销, 主要表现在一下两方面:
1. 上下文切换(context switch), 此处有4次用户态和内核态的切换
2. Buffer内存开销, 一个是应用程序buffer, 另一个是系统读取buffer以及socket buffer
其运行示意图如下
这里写图片描述

1) 先将文件内容从磁盘中拷贝到操作系统buffer
2) 再从操作系统buffer拷贝到程序应用buffer
3) 从程序buffer拷贝到socket buffer
4) 从socket buffer拷贝到协议引擎.

NIO(同步非阻塞的IO):

NIO技术省去了将操作系统的read buffer拷贝到程序的buffer, 以及从程序buffer拷贝到socket buffer的步骤, 直接将 read buffer 拷贝到 socket buffer. java 的 FileChannel.transferTo() 方法就是这样的实现, 这个实现是依赖于操作系统底层的sendFile()实现的.
publicvoid transferTo(long position, long count, WritableByteChannel target);
他的底层调用的是系统调用sendFile()方法
sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
如下图

这里写图片描述

AIO–(异步非阻塞的IO):

伪异步:

这里写图片描述

真正的异步(NIO原理):

真正的异步是与操作系统底层去交互的。
这里写图片描述

案例:NIO写socket

服务端代码:
创建selector
打开channel
设置channel为非阻塞
channel绑定端口
注册channel到selector上,注册为接受请求事件
这里写图片描述

看看哪些channel上有消息 (selectedKeys就是活跃的消息对应的channel。)

遍历获取每一个活跃的key.
每拿到一个key就把他从队列里移除。并且处理这个key
这里写图片描述
获取这个活跃key对应的channel,建立连接,配置非阻塞
注册一个新的事件——“读”
这里写图片描述

这里写图片描述

客户端代码:
这里写图片描述

。。。。略

我们发现 直接用NIO写socket太麻烦。
所以我们生产中不直接用

我们用netty这样的 对NIO封装的框架

0 0