Как отладить «Несоответствие сокета канала Java NIO по размеру отправляемых и получаемых байтов»? - PullRequest
0 голосов
/ 11 января 2019

Пожалуйста, посмотрите на этот вопрос .

Это именно то, что я ищу, но я еще не достиг этого. Я отправляю несколько изображений через socketChannel. Я пытаюсь прикрепить размер изображения в (очищенный ByteBuffer) и затем присоединить данные изображения в тот же буфер (размер буфера достаточно большой!).

Сначала на принимающей стороне размер изображения будет считан ByteBuffer.read (...), затем ByteBuffer.flip () и ByteBuffer.getLong () (например, imageData = readBuffer.getLong ()), чтобы прочитать следующие данные изображения, я делаю ByteBuffer.comact ()? Как я понимаю, что будет прочитано точное количество байтов imageData?

Нет, у меня есть следующее: На стороне отправителя:

socketChannelEntity.getWriteBuffer().clear();
            if(socketChannelEntity.getFileToProcessCounter() < fileList.size()){
                this.fileName = fileList.get(socketChannelEntity.getFileToProcessCounter()).toString();
                System.out.println("NIO_CLIENT: " + socketChannelEntity.getEntityName() + ": Send next image: " + fileName);
            } else {
                System.out.println("NIO_CLIENT: No more images to send.");
                socketChannelEntity.setSendReceiveStatus(SendReceiveStatusClient.DONE);
                socketChannel.register(this.selector, SelectionKey.OP_READ, socketChannelEntity);
                return;
            }
            Path path = Paths.get(fileName);
            long fileSize = Files.size(path);
            System.out.println(fileName + " size: " + fileSize);
            socketChannelEntity.getWriteBuffer().putLong(fileSize);
            try{
                FileChannel fileChannel = FileChannel.open(path);
                int numRead = 0;
                int counter = 0;
                while((numRead = fileChannel.read(socketChannelEntity.getWriteBuffer())) > 0){
                    counter += numRead;
                    socketChannelEntity.getWriteBuffer().flip();
                    do {
                        numRead -= socketChannel.write(socketChannelEntity.getWriteBuffer());
//                      socketChannelEntity.getWriteBuffer().clear();
                    } while (numRead > 0);
                }
                fileChannel.close();
                System.out.println("NIO_CLIENT: " + socketChannelEntity.getEntityName() + ": Image " + fileName + " sent: " + counter + " bytes long");
                socketChannelEntity.setCheckSum(fileSize);
                socketChannelEntity.setSendReceiveStatus(SendReceiveStatusClient.RECEIVE_CHECKSUM_IMAGE);
            } catch(IOException e) {
                e.printStackTrace();
            }

На стороне получателя:

if(socketChannel.socket().getLocalPort() == 10000){
                outputFile =  Config.HOME_PATH_SERVER_1 + "receivedImage" + fileNameCounter + ".jpg";
            } else if(socketChannel.socket().getLocalPort() == 10001){
                outputFile =  Config.HOME_PATH_SERVER_2 + "receivedImage" + fileNameCounter + ".jpg";
            }
            Path path = Paths.get(outputFile);
            FileChannel fileChannel = FileChannel.open(path,
                    EnumSet.of(StandardOpenOption.CREATE,
                            StandardOpenOption.TRUNCATE_EXISTING,
                            StandardOpenOption.WRITE));
            int numRead = 0;
            int counter = 0;
            readBuffer.clear();
            socketChannel.read(readBuffer);
            readBuffer.flip();
            checkSum = readBuffer.getLong();
            System.out.println("Server erwartet ein Bild der Groesse: " + checkSum);
            readBuffer.limit((int)checkSum+8);
            fileChannel.write(readBuffer);
            fileChannel.close();
            if(readBuffer.hasRemaining()){
                System.out.println("Ist noch was im ReadBuffer!");
            }
            prepareWriteBuffer(checkSum);
            System.out.println("NIO_SERVER: Received image.");
            sendReceiveStatus = SendReceiveStatusServer.SEND_CHECKSUM_IMAGE;

Для первого изображения все работает нормально. Счетчик файлов на стороне отправителя увеличивается, и отправитель пытается отправить следующее изображение. Сторона получателя получает сейчас: размер для следующего изображения: например. 1591323337052742968 Что не так?

1 Ответ

0 голосов
/ 11 января 2019

Попробуйте это:
На стороне клиента (отправляющая)

  1. Запишите размер изображения в ByteBuffer (ByteBuffer.putLong).
  2. Записать данные изображения в тот же ByteBuffer (ByteBuffer.put(byte[])).
  3. Звоните ByteBuffer.flip.
  4. Запишите ByteBuffer в канал сокета.

На стороне сервера (принимающей)

  1. Чтение из канала сокета в ByteBuffer.
  2. Звоните ByteBuffer.flip.
  3. Получите длину изображения из ByteBuffer (ByteBuffer.getLong).
  4. Выделите байт изображения [] (используя размер изображения).
  5. Считать изображение из ByteBuffer (ByteBuffer.get(byte[])).
...