Netty的深入浅出--35.零拷贝实例剖析
下面写两个程序一个基于IO的,一个基于NIO的。将两个进行对比看出优劣;
对比方法:客户端不断的从磁盘中读取数据到服务端,服务端收到数据之后丢弃。最后对比两种方式所消耗的时间。
IO操作:
服务端:
客户端:
启动服务端:
启动客户端:
运行很多次之后,发现耗时基本上停留在400多毫秒
NIO:
服务端:
这里设置了一个socket属性:
我们查看一下它的源码 的dom说明:
该方法是禁用或者启动SocketOptions这个属性
描述的是:在连接关闭之后,但是tcp连接可能处于的是一种超时的状态,这种状态称为一种time_wait状态
当处于上面所说的time_wait之后,是不能绑定到这个socke端口号上的。一但尝试绑定就会报这个地址已经被占用的警告。因为虽然断开了连接,但是还是只是处于一种超时的状态,没有释放掉这个socket端口号,简单来说就是:占着坑位,不过干事。
所以说,当我们使用了setreuseaddress方法之后,我们就可以使用这种处于time_out状态下的端口号了
当连接上之后会获得一个通道:
accept方法的dom源码:
如果是非阻塞的话,在未连接的情况下返回时null
如果是阻塞的话,在未连接的情况下会一直阻塞式等待连接
不过它返回的socket方法,一定是阻塞模式的
它默认情况下都是阻塞的,如果我们不设置其实也是可以的,但是如果有selector的话,一定要使用非阻塞的。
将数据读到bytebuffer当中:
现在我们需要重新将bytebuffer的position和limit位置回到初始位(之前我们采用的是clear或者flip两种方式):
查看rewind方法源码:
客户端:
获取socketChannel对象
向服务器端发起连接:
在之前使用selector管理channel的时候,我们设置的是非阻塞的,现在由于只有一个客户端,而且并没有使用selector,所以我们直接使用阻塞式就可以了
获取文件通道
第一个方法transferFrom:将数据读到channel通道中来
第二个方法transferTo:将数据写到writeByteChannel中去;
然后传递到socketChannel;
返回的是实际传递的数量
查看transferTo方法源码:
将传递的字节放入到能够写的byte channel中
如果采用的是非阻塞的形式的话,读取的字节数量会相比更少:
重点:这个方法比我们之前使用循环不断从filechannel中读取数据效率更高 !
重点:在一些操作系统中直接将字节传送到文件系统缓存中,而不是去先将他们复制一份。这就是之前说的零拷贝。
打印:
启动服务器:
启动客户端:
对比之前IO耗时,发现性能上效率上提高了很多。