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

时间:2017-06-24 03:35:06

标签: java buffer limit

我不知道原因,但无法发送长度超过20,000字节的对象。我喜欢缓冲区的长度低于剩余的长度。我该如何解决这个问题?使用Grizzly和大使图书馆。发送小值时一切都还可以。

系统输出

  1. [05:44:04 INFO]:14480
  2. [05:44:04 INFO]:STOPED3 14480< 20636
  3. [05:44:04 INFO]:20557
  4. [05:44:04 INFO]:STOPED2 20557< 1229410144
  5. 我的代码:

    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);
    

1 个答案:

答案 0 :(得分:0)

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

在我的猜测中,当发送数据小于20000字节时,发送数据不会被分割成不同的数据包,因此handleRead()每次都会读取完全字节,但它会被分成几个数据包虽然发送数据很大,但$query .= "Select red, green, blue from colorsDB where signoff is not null"; $db->setQuery($query); $query = $db->loadObjectList(); 可能会读取发送数据的一部分。

相关问题