Java 缓冲区 - 无法发送长度大于 20kb 的对象

Java Buffer - Cannot send object with length bigger than 20kb

不知道为什么,不能发送长度大于20,000字节的对象。我喜欢缓冲区的长度小于剩余长度。我该如何解决?使用 Grizzly 和 Ambassador 库。虽然发送小值一切正常。

系统输出

  1. [05:44:04 信息]:14480
  2. [05:44:04 信息]:STOPED3 14480 < 20636
  3. [05:44:04 信息]:20557
  4. [05:44:04 信息]:STOPED2 20557 < 1229410144

我的代码:

private static final int HEADER_SIZE = 12;

@Override
public NextAction handleRead(final FilterChainContext ctx) throws IOException {
    final Buffer buffer = ctx.getMessage();
    System.out.println(buffer.limit());
    final int total = buffer.remaining();
    if (total < HEADER_SIZE) {
        System.out.println("STOPED1 "+"  "+total+" < "+HEADER_SIZE);
        return ctx.getStopAction(buffer);
    }
    buffer.get();
    buffer.get();
    buffer.get();
    buffer.get();
    int len = buffer.getInt();
    if (total < HEADER_SIZE + len) {
        System.out.println("STOPED2 "+"  "+total+" < "+(HEADER_SIZE+len));
        return ctx.getStopAction(buffer);
    }
    byte[] pack = new byte[len];
    buffer.get(pack);
    String name = new String(pack);
    int size = buffer.getInt();
    final int completeMessageLength = HEADER_SIZE + size + len;
    if (total < completeMessageLength) {
        System.out.println("STOPED3 "+"  "+total+" < "+completeMessageLength);
        return ctx.getStopAction(buffer);
    }
    final Buffer remainder = total > completeMessageLength ? buffer.split(completeMessageLength) : null;
    System.out.println("PACKET[IN] Name: " + name + " Size: " + total + " BodySize: " + buffer.remaining());
    byte[] body = new byte[size];
    buffer.get(body);
    Packet packet = null;
    try {
        packet = getPacket(name);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    if (packet == null) {
        return ctx.getInvokeAction(remainder);
    }
    packet.read(body);
    handlePacket(ctx.getConnection(), packet);
    return ctx.getInvokeAction(remainder);
}

@Override
public NextAction handleWrite(final FilterChainContext ctx) throws IOException {
    Packet packet = ctx.getMessage();
    String name = packet.getClass().getName();
    byte[] packetBody = name.getBytes();
    byte[] body = packet.write();
    int bodyLen = body.length;
    int packetLen = packetBody.length;
    final MemoryManager memoryManager = ctx.getConnection().getTransport().getMemoryManager();
    int size = HEADER_SIZE + bodyLen + packetLen;
    final Buffer output = memoryManager.allocate(size);
    output.allowBufferDispose(true);
    output.put((byte) 0);
    output.put((byte) 0);
    output.put((byte) 0);
    output.put((byte) 0);
    output.putInt(packetLen);
    output.put(packetBody);
    output.putInt(bodyLen);
    output.put(body);
    ctx.setMessage(output.flip());
    System.out.println("PACKET[OUT] ID: " + name + " Size: " + size);
    return ctx.getInvokeAction();
}

protected static Packet getPacket(String name) throws IllegalAccessException {
    try {
        Class cl = Class.forName(name);
        return (Packet) cl.newInstance();
    } catch (ClassNotFoundException | InstantiationException e) {
        e.printStackTrace();
    }
    return null;
}


protected abstract void handlePacket(Connection connection, Packet packet);

在你上面的代码中,当条件为假时,你不会撤回 buffer 位置:if (total < HEADER_SIZE + len)if (total < completeMessageLength)。我认为你应该 mark()在你从 bufffer 读取任何内容之前的位置,然后,如果 buffer 不完整,你应该 reset() 该位置,以便 handleRead() 方法可以读取数据header下次正确。

我猜,当发送数据小于20000字节时,发送数据不会拆分成不同的数据包,所以handleRead()每次都会读取完整字节,但会拆分成发送数据量大时有多个数据包,所以handleRead()可能会读取一部分发送数据。