netty实例之路1

来源:互联网 发布:淘宝网下载 编辑:程序博客网 时间:2024/06/08 07:17

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:

@Overridepublic ByteBuffer nioBuffer(int index, int length) {    ensureAccessible();    return ByteBuffer.wrap(array, index, length).slice();}@Overridepublic 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.之后不断地在二者间往返查看函数的实现即可。
@Overridepublic int capacity() {    ensureAccessible();    return array.length;}@Overridepublic 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有介绍。
@Overridepublic 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个基本的函数@Overridepublic int readableBytes() {    return writerIndex - readerIndex;}@Overridepublic int writableBytes() {    return capacity() - writerIndex;}
setIndex函数:@Overridepublic 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);    }}

读取

@Overridepublic 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;}

写入:

@Overridepublic ByteBuf writeBytes(byte[] src, int srcIndex, int length) {    ensureAccessible();    ensureWritable(length);    setBytes(writerIndex, src, srcIndex, length);    writerIndex += length;    return this;}setBytes在UnpooledHeapByteBuf中。
@Overridepublic 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);}

重用缓冲区

@Overridepublic 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;    }}

忽略部分字段

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

@Overridepublic ByteBuf skipBytes(int length) {    checkReadableBytes(length);    readerIndex += length;    return this;}checkReadableBytes在  读取  部分已经谈过。
0 0
原创粉丝点击