package org.kne.cloud.network.perf; import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.klalb.KLALBPacket; public class TESTNPacket extends KLALBPacket { private static final int HEADER_LENGTH = 3; // 核心:一个线程私有的 65535 字节大缓存,生命周期与线程同寿 private static final ThreadLocal BENCH_BUFFER = ThreadLocal.withInitial(() -> ByteBuffer.allocate(65535)); // 不再持有 ByteBuffer,只记录长度 private int payloadLength; @Override public long getTotalLength() { return HEADER_LENGTH + payloadLength; } // 发送端构造 public TESTNPacket(int limit) { super(TESTN, HEADER_LENGTH); this.payloadLength = limit; } // 接收端构造(从已有的 ByteBuffer 解析) public TESTNPacket(ByteBuffer bb) { super(bb, HEADER_LENGTH); this.payloadLength = klalbHeader.getChar(1); } public int getPayloadLength() { return payloadLength; } @Override public void writeToChannel(WritableByteChannel dto) throws IOException { // 1. 写入包头(包含 payloadLength) klalbHeader.putChar(1, (char) payloadLength); super.writeToChannel(dto); // 2. 如果有 payload,借用 ThreadLocal 缓冲区并写出去 if (payloadLength > 0) { ByteBuffer buf = BENCH_BUFFER.get(); buf.clear(); buf.limit(payloadLength); // 限制到指定长度 // 直接写出,里面的数据是上一次残留的或者全 0,对于烤机无所谓 dto.write(buf); } } @Override public void readFromChannel(ReadableByteChannel din) throws IOException { // 1. 读包头 super.readFromChannel(din); this.payloadLength = klalbHeader.getChar(1); // 2. 如果有 payload,借用缓冲区接收数据 if (payloadLength > 0) { ByteBuffer buf = BENCH_BUFFER.get(); buf.clear(); buf.limit(payloadLength); // 循环读满(使用你现有的 KNEChannels 工具或手动循环) while (buf.hasRemaining()) { if (din.read(buf) == -1) { throw new EOFException("连接提前断开,未能读满 TESTN 载荷"); } } // 数据读完直接丢弃,缓冲区不保存,下一次 clear() 时会自动覆盖 } } @Override public String toString() { return "TESTN[" + payloadLength + "]"; } }