netty отправляет посылку частями
В моем коде возникает ошибка, когда я посылаю файл два раза(или больше) подряд. Мне удалось разобраться, что причиной ее возникновения является то, что отправленная посылка разбивается на две части (заголовок(1 часть) + тело файла(2 часть)), и сервер не может полноценно её принять, так как хендлер ждет на вход определенный управляющий байт, который, естественно не приходит. Я исчерпал все свои идеи, как это можно исправить, быть может они есть у вас? Вот мой код. Тут я отправляю посылку:
while (true) {
inputLine = bufferedReader.readLine().trim().toLowerCase();
String firstCommand = inputLine.split(" ")[0];
switch (firstCommand) {
case "up":
sendCommand(inputLine);
long parcelSize = 0;
String fileName = getSecondElement(inputLine);
Path path = Path.of(HOME_FOLDER_PATH + fileName);
FileRegion region = null;
ByteBuf buf = null;
region = new DefaultFileRegion(new FileInputStream(path.toFile()).getChannel(), 0, Files.size(path));
parcelSize = getParcelSize(parcelSize, path);
buf = ByteBufAllocator.DEFAULT.directBuffer(1);
buf.writeByte((byte) 2);
buf.retain();
client.getChannel().write(buf);
buf = ByteBufAllocator.DEFAULT.directBuffer(8);
buf.writeLong(parcelSize);
buf.retain();
client.getChannel().write(buf);
buf = ByteBufAllocator.DEFAULT.directBuffer(4);
buf.writeInt(path.getFileName().toString().length());
buf.retain();
client.getChannel().write(buf);
byte[] filenameBytes = path.getFileName().toString().getBytes();
buf = ByteBufAllocator.DEFAULT.directBuffer(filenameBytes.length);
buf.writeBytes(filenameBytes);
buf.retain();
client.getChannel().write(buf);
buf = ByteBufAllocator.DEFAULT.directBuffer(8);
buf.writeLong(Files.size(path));
buf.retain();
client.getChannel().write(buf);
System.out.println("parcelSize: " + parcelSize);
ChannelFuture transferOperationFuture = client.getChannel().write(region);
client.getChannel().flush();
break;
default:
throw new IllegalStateException("Unexpected value: " + inputLine);
}
}
А тут я ее получаю:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = ((ByteBuf) msg);
byte readed = buf.readByte();
Command command = Command.valueOf(readed);
if (currentState == State.IDLE) {
switch (command) {
case DOWNLOAD:
break;
default:
invalidControlByte(buf, "(class ServerHandler) ERROR: Invalid first byte - ", readed);
break;
}
}
receivedFileLength = 0;
if (currentState == State.IDLE) {
currentState = State.PARCEL_LENGTH;
System.out.println("Client: Start file receiving");
}
if (currentState == State.PARCEL_LENGTH) {
if (buf.readableBytes() < 8) return;
if (buf.readableBytes() >= 8) {
parcelSize = buf.readLong();
System.out.println("STATE: PARCEL_LENGTH received - " + parcelSize);
currentState = State.NAME_LENGTH;
}
}
if (currentState == State.NAME_LENGTH) {
if (buf.readableBytes() < 4) return;
if (buf.readableBytes() >= 4) {
System.out.println("STATE: Get filename length");
nextLength = buf.readInt();
currentState = State.NAME;
}
}
if (currentState == State.NAME) {
if (buf.readableBytes() < nextLength) return;
if (buf.readableBytes() >= nextLength) {
byte[] fileName = new byte[nextLength];
buf.readBytes(fileName);
System.out.println("STATE: Filename received - _" + new String(fileName));
out = new BufferedOutputStream(new FileOutputStream("project/server/cloud_storage/" + new String(fileName)));
currentState = State.FILE_LENGTH;
}
}
if (currentState == State.FILE_LENGTH) {
if (buf.readableBytes() < 8) return;
if (buf.readableBytes() >= 8) {
fileLength = buf.readLong();
System.out.println("STATE: File length received - " + fileLength);
currentState = State.FILE;
}
}
if (currentState == State.FILE) {
while (buf.readableBytes() > 0) {//Записываем в цикле напрямую в файл
out.write(buf.readByte());
receivedFileLength++;
if (fileLength == receivedFileLength) {
currentState = State.IDLE;
System.out.println("File received");
out.close();
buf.clear();
}
}
}
}