Если я пишу длинный запрос на сервер, к примеру 5000 байтов, то приходит только 1024, а потом приходит остальная часть.
Один человек мне написал, что байты делятся на чанки, чтобы не было OutOfMemory. На другом форуме мне сказали нужно читать все байты, если их не хватает то дочитывать остальные, я пытался сделать, но в голову прилетел тапок, на подошве которого было написано: "Не так читаешь, лови стактрейс на 100500 символов"
Думал может уже есть готовые решения, но в инете ничего не нашёл, кроме ChunkedWriteHandler, но он ничего не сделал.
Написал полностью чистый клиент-сервер, на 2х пакетах, InMessage & OutMessage. Вот что происходит без склейки:
io.netty.handler.codec.DecoderException: org.whileinside.nettyTests.exceptions.BadPacket: Couldn't read packet: 0. Cause: readerIndex(6) + length(5000) exceeds writerIndex(1024): PooledUnsafeDirectByteBuf(ridx: 6, widx: 1024, cap: 1024)
Далее влетает ещё одна ошибка
io.netty.handler.codec.DecoderException: org.whileinside.nettyTests.exceptions.BadPacket: Unknown packet id: 12597
Надеюсь мне кто-нибудь поможет =)
Edit 1: Код
Запуск клиента
Bootstrap b = new Bootstrap()
.option(ChannelOption.TCP_NODELAY, true)
.channel(NioSocketChannel.class)
.group(worker = new NioEventLoopGroup(2))
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast("packetDecoder", new PacketDecoder())
.addLast("packetEncoder", new PacketEncoder())
.addLast("chunkedWrite", new ChunkedWriteHandler())
.addLast("handler", new ClientHandler());
}
});
ChannelFuture future = b.connect("127.0.0.1", 2345).sync();
if (future.isSuccess()) {
System.out.println("Successfully started!");
}
future.channel().closeFuture();
Запуск сервера
ServerBootstrap b = new ServerBootstrap()
.childOption(ChannelOption.TCP_NODELAY, true)
.channel(NioServerSocketChannel.class)
.group(worker = new NioEventLoopGroup(2))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast("packetDecoder", new PacketDecoder())
.addLast("packetEncoder", new PacketEncoder())
.addLast("chunkedWrite", new ChunkedWriteHandler())
.addLast("handler", new ServerHandler());
}
});
ChannelFuture future = b.bind("127.0.0.1", 2345).sync();
future.channel().closeFuture();
PacketEncoder & PacketDecoder
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
PacketBuffer buffer = new PacketBuffer(in);
while(buffer.isReadable()) {
out.add(PacketManager.readPacket(new PacketBuffer(in)));
}
}
@Override
protected void encode(ChannelHandlerContext ctx, Packet msg, ByteBuf out) throws Exception {
PacketBuffer buffer = new PacketBuffer(out);
out.writeShort(PacketArray.getPacketID(msg.getClass()));
msg.write(buffer);
}
PacketManager::readPacket
public static Packet readPacket(PacketBuffer buf) {
short id = buf.readShort();
if(!PacketArray.containsPacket(id)) {
throw new BadPacket("Unknown packet id: " + id);
}
try {
Packet packet = PacketArray.searchPacket(id);
packet.read(buf);
return packet;
} catch(Exception e) {
throw new BadPacket("Couldn't read packet: " + id + ". Cause: " + e.getMessage());
}
}
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости