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
- netty实例之路1
- Netty心跳检测篇之简单实例
- Netty学习之路(1)
- Netty 实例
- Netty实例
- Netty实例
- Netty学习开发之路
- 1 netty之NIO介绍
- Netty学习之二--Java socket编程(UDP实例)
- netty系列1-JAVA IO演进之路
- 【Netty】Netty系列之Netty可靠性分析
- 【Netty】Netty系列之Netty线程模型
- netty简单实例
- Netty使用实例
- netty入门实例
- netty入门实例
- netty Demo 实例
- Netty使用实例
- Socket通讯原理
- 解决SSH自动断线,无响应的问题
- MATLAB中imfilter函数用Opencv 实现遇到的若干问题
- ButterKnife源码分析
- RxJava----操作符:条件和布尔操作符
- netty实例之路1
- Java协变数组和类型擦除
- centos下文件颜色
- Android定位
- 过滤器与拦截器区别
- 软件开发管理模型及分析比较
- NSTimer和CADisplayLink
- 指针数组和数组指针的区别
- Java的异或运算