netty实例之路1

2016.4.26
根据《netty权威指南第二版》启发,后文称为NQ2。
系列文章基于netty-4.0.36.Final,官网有下载。

NQ2 page309有bytebuf的继承关系。从某个具体子类开始,往上递推,这样比较容易有感性认识。

全文的函数定义主要在UnpooledHeapByteBuf(UHBB)和AbstractByteBuf(ABB)见来回跳跃,分为2个模块,比较清晰。

UnpooledHeapByteBuf

首先看到定义:

public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {

        private final ByteBufAllocator alloc;
        byte[] array;
        private ByteBuffer tmpNioBuf;
        ... 
}

因为通过NIO进行网络读写时,操作的对象是JDK标准的java.io.ByteBuffer,所以必须把netty的ByteBuf转换为ByteBuffer:

@Override
public ByteBuffer nioBuffer(int index, int length) {
    ensureAccessible();
    return ByteBuffer.wrap(array, index, length).slice();
}

@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
    checkDstIndex(index, length, dstIndex, dst.length);
    System.arraycopy(array, index, dst, dstIndex, length);
    return this;
}
这里的checkDstIndex来自AbstractByteBuf.之后不断地在二者间往返查看函数的实现即可。
@Override
public int capacity() {
    ensureAccessible();
    return array.length;
}

@Override
public ByteBuf capacity(int newCapacity) {
    ensureAccessible();
    if (newCapacity < 0 || newCapacity > maxCapacity()) {
        throw new IllegalArgumentException("newCapacity: " + newCapacity);
    }

    int oldCapacity = array.length;
    if (newCapacity > oldCapacity) {
        byte[] newArray = new byte[newCapacity];
        System.arraycopy(array, 0, newArray, 0, array.length);
        setArray(newArray);
    } else if (newCapacity < oldCapacity) {
        byte[] newArray = new byte[newCapacity];
        int readerIndex = readerIndex();
        if (readerIndex < newCapacity) {
            int writerIndex = writerIndex();
            if (writerIndex > newCapacity) {
                writerIndex(writerIndex = newCapacity);
            }
            System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex);
        } else {
            setIndex(newCapacity, newCapacity);
        }
        setArray(newArray);
    }
    return this;
}
在NQ2的322~323有介绍。
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
    checkSrcIndex(index, length, srcIndex, src.length);
    System.arraycopy(src, srcIndex, array, index, length);
    return this;
}
checkSrcIndex和checkDstIndex很类似。

AbstractByteBuf

2个基本的函数
@Override
public int readableBytes() {
    return writerIndex - readerIndex;
}

@Override
public int writableBytes() {
    return capacity() - writerIndex;
}
setIndex函数:
@Override
public ByteBuf setIndex(int readerIndex, int writerIndex) {
    if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
        throw new IndexOutOfBoundsException(String.format(
                "readerIndex: %d, writerIndex: %d (expected: 0 <= readerIndex <= writerIndex <= capacity(%d))",
                readerIndex, writerIndex, capacity()));
    }
    setIndex0(readerIndex, writerIndex);
    return this;
}

final void setIndex0(int readerIndex, int writerIndex) {
    this.readerIndex = readerIndex;
    this.writerIndex = writerIndex;
}
protected final void ensureAccessible() {
    if (checkAccessible && refCnt() == 0) {
        throw new IllegalReferenceCountException(0);
    }
}

读取

@Override
public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
    checkReadableBytes(length);
    getBytes(readerIndex, dst, dstIndex, length);
    readerIndex += length;
    return this;
}
这里的getBytes具体实现在UnpooledHeapByteBuf中。
protected final void checkReadableBytes(int minimumReadableBytes) {
    if (minimumReadableBytes < 0) {
        throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)");
    }
    checkReadableBytes0(minimumReadableBytes);
}

private void checkReadableBytes0(int minimumReadableBytes) {
    ensureAccessible();
    if (readerIndex > writerIndex - minimumReadableBytes) {
        throw new IndexOutOfBoundsException(String.format(
            "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",
            readerIndex, minimumReadableBytes, writerIndex, this));
    }
}
protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity){
    checkIndex(index, length);
    if (isOutOfBounds(dstIndex, length, dstCapacity)) {
        throw new IndexOutOfBoundsException(String.format("dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity));
    }
}
protected final void checkIndex(int index, int fieldLength) {
    ensureAccessible();
    checkIndex0(index, fieldLength);
}

final void checkIndex0(int index, int fieldLength) {
    if (isOutOfBounds(index, fieldLength, capacity())) {
        throw new IndexOutOfBoundsException(String.format(
                "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity()));
    }
}

此处的isOutOfBounds在MathUtil中
public static boolean isOutOfBounds(int index, int length, int capacity) {
    return (index | length | (index + length) | (capacity - (index + length))) < 0;
}

写入:

@Override
public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
    ensureAccessible();
    ensureWritable(length);
    setBytes(writerIndex, src, srcIndex, length);
    writerIndex += length;
    return this;
}
setBytes在UnpooledHeapByteBuf中。

@Override
public ByteBuf ensureWritable(int minWritableBytes) {
    if (minWritableBytes < 0) {
        throw new IllegalArgumentException(String.format(
                "minWritableBytes: %d (expected: >= 0)", minWritableBytes));
    }
    ensureWritable0(minWritableBytes);
    return this;
}

private void ensureWritable0(int minWritableBytes) {
    if (minWritableBytes <= writableBytes()) {
        return;
    }
    if (minWritableBytes > maxCapacity - writerIndex) {
        throw new IndexOutOfBoundsException(String.format(
                "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
                writerIndex, minWritableBytes, maxCapacity, this));
    }
    // Normalize the current capacity to the power of 2.
    int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes);
    // Adjust to the new capacity.
    capacity(newCapacity);
}
这里的capacity()在UnpooledHeapByteBuf里。

这里的calculateNewCapacity在NQ2的page314~315有详细说明,不再赘述。

private int calculateNewCapacity(int minNewCapacity) {
    final int maxCapacity = this.maxCapacity;
    final int threshold = 1048576 * 4; // 4 MiB page

    if (minNewCapacity == threshold) {
        return threshold;
    }

    // If over threshold, do not double but just increase by threshold.
    if (minNewCapacity > threshold) {
        int newCapacity = minNewCapacity / threshold * threshold;
        if (newCapacity > maxCapacity - threshold) {
            newCapacity = maxCapacity;
        } else {
            newCapacity += threshold;
        }
        return newCapacity;
    }

    // Not over threshold. Double up to 4 MiB, starting from 64.
    int newCapacity = 64;
    while (newCapacity < minNewCapacity) {
        newCapacity <<= 1;
    }

    return Math.min(newCapacity, maxCapacity);
}

重用缓冲区

@Override
public ByteBuf discardReadBytes() {
    ensureAccessible();
    if (readerIndex == 0) {
        return this;
    }

    if (readerIndex != writerIndex) {
        setBytes(0, this, readerIndex, writerIndex - readerIndex);
        writerIndex -= readerIndex;
        adjustMarkers(readerIndex);
        readerIndex = 0;
    } else {
        adjustMarkers(readerIndex);
        writerIndex = readerIndex = 0;
    }
    return this;
}

针对 if (readerIndex != writerIndex) 分析一下:
把readerIndex到 writerIndex - readerIndex的内容往前挪,
然后调整Buf的marker

protected final void adjustMarkers(int decrement) {
    int markedReaderIndex = this.markedReaderIndex;
    if (markedReaderIndex <= decrement) {
        this.markedReaderIndex = 0;
        int markedWriterIndex = this.markedWriterIndex;
        if (markedWriterIndex <= decrement) {
            this.markedWriterIndex = 0;
        } else {
            this.markedWriterIndex = markedWriterIndex - decrement;
        }
    } else {
        this.markedReaderIndex = markedReaderIndex - decrement;
        markedWriterIndex -= decrement;
    }
}

忽略部分字段

解码的时候,直接忽略这段数据读取后面的缓冲区内容。

@Override
public ByteBuf skipBytes(int length) {
    checkReadableBytes(length);
    readerIndex += length;
    return this;
}
checkReadableBytes在  读取  部分已经谈过。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值