深入了解LINUX下IO模式(二)——什么是面向流,什么是面向缓冲区

5 篇文章 0 订阅

面向流,面向缓冲区,这是JAVA中的概念,和操作系统无关


具体怎么看呢,废话少说直接上源码


第一段是JAVA中的标准IO

java.net.SocketInputStream.read
 
int read(byte b[], int off, int length, int timeout) throws IOException {
int n;
 
 
 
// EOF already encountered
if (eof) {
return -1;
}
 
// connection reset
if (impl.isConnectionReset()) {
throw new SocketException("Connection reset");
}
 
// bounds check
if (length <= 0 || off < 0 || off + length > b.length) {
if (length == 0) {
return 0;
}
throw new ArrayIndexOutOfBoundsException();
}
 
boolean gotReset = false;
 
// acquire file descriptor and do the read
FileDescriptor fd = impl.acquireFD();
try {
n = socketRead(fd, b, off, length, timeout);//native函数
if (n > 0) {
return n;
}
} catch (ConnectionResetException rstExc) {
gotReset = true;
} finally {
impl.releaseFD();
}
 
/*
* We receive a "connection reset" but there may be bytes still
* buffered on the socket
*/
if (gotReset) {
impl.setConnectionResetPending();
impl.acquireFD();
try {
n = socketRead(fd, b, off, length, timeout);//native函数,这里从内核态中读取数据到数组b中
if (n > 0) {
return n;
}
} catch (ConnectionResetException rstExc) {
} finally {
impl.releaseFD();
}
}
 
/*
* If we get here we are at EOF, the socket has been closed,
* or the connection has been reset.
*/
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
}
if (impl.isConnectionResetPending()) {
impl.setConnectionReset();
}
if (impl.isConnectionReset()) {
throw new SocketException("Connection reset");
}
eof = true;
return -1;
}
  
第二段代码是一般说的NIO实现方式
sun.nio.ch.DatagramChannelImpl.receive
private int receive(FileDescriptor fd, ByteBuffer dst)
        throws IOException
    {
        int pos = dst.position();
        int lim = dst.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
        if (dst instanceof DirectBuffer && rem > 0)
            return receiveIntoNativeBuffer(fd, dst, rem, pos);

        // Substitute a native buffer. If the supplied buffer is empty
        // we must instead use a nonempty buffer, otherwise the call
        // will not block waiting for a datagram on some platforms.
        int newSize = Math.max(rem, 1);
        ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);//申请一块newSize大小的缓冲区块
        try {
            int n = receiveIntoNativeBuffer(fd, bb, newSize, 0);//数据读取到缓冲区中,buffer可以做标记,操作指针等
            bb.flip();
            if (n > 0 && rem > 0)
                dst.put(bb);
            return n;
        } finally {
            Util.releaseTemporaryDirectBuffer(bb);
        }
    }
  
可以看到,第一段代码中一次性从native函数中获取相当长度的数据,然后直接对这块数据进行了操作
而第二段代码中Util.getTemporaryDirectBuffer(newSize);申请了一块堆外内存,每次读取的数据放在该内存中,然后对该内存进行操作。
一般说法面向缓存相对于面向流的好处在于增加了处理数据的灵活性,当然也增加了操作的复杂度,比如当更多数据取入时,是否会覆盖前面的数据等 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值