Циклы Java NIO на socketChannel.read()

Я безуспешно пытаюсь понять, где ошибка. Сценарий представляет собой клиент, который подключается к серверу, который получает файл, своего рода «загрузку». Затем сервер открывает FileChannel, считывает все данные и сохраняет их в буфере, который копируется в локальный файл.

СЕРВЕР

ServerSocketChannel ssf = ...//[Initialized into the costrutor]
    SocketChannel clientf = null;

    Path path = Paths.get(new File("").getAbsolutePath()+"/"+"example.txt");

    try {
        // Creating file to write
        FileChannel file = FileChannel.open(path, EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE));

        clientf = ssf.accept();

        System.out.println("Client is connected");

        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int i=0;
        //Here I'll read the data sent from the client
        while (clientf.read(buffer) > 0) { //LOOP1

            buffer.flip();

            while (buffer.hasRemaining()) { //LOOP2
                file.write(buffer);
            }

            buffer.clear();
            i++; // Used in order to know how many iteration are performed
        }

        file.close();
        System.out.println("File received");

    } catch(IOException e){
            e.printStackTrace();
    }

    finally {
            // CLose all the open connections
        if(ssf != null) {
            try {

                if(clientf != null)
                    clientf.close();

                ssf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

КЛИЕНТ

 byte[] message = new byte[x];
            in.readFully(message, 0, message.length);

            try {

                SocketChannel sockfile = SocketChannel.open();
                //sockfile.configureBlocking(false); //If this line is executed the client doesn't connect. Why?
                sockfile.connect(new InetSocketAddress(ip, portfile));
                File f = new File("");
                f = new File(f.getAbsoluteFile()+"/"+file);
                RandomAccessFile af = new RandomAccessFile(f,"r");
                FileChannel inCh = af.getChannel();

                ByteBuffer buffer = ByteBuffer.allocate(1024);

                while (inCh.read(buffer) > 0) {

                    buffer.flip();

                    while(buffer.hasRemaining()) {
                        sockfile.write(buffer);
                    }

                    buffer.clear();
                }

                af.close();

            } catch (ParseException e) {
                e.printStackTrace();
            }

            System.out.println("File sent");

Клиент завершает работу, так как печатает File sent. Вместо этого сервер не выходит из LOOP1. Я не понимаю, почему read() в стороже loop1 всегда читает 1024 байта (это значение пришло из отладки), даже если клиент закрыл канал (фактически он остановил весь поток).

Есть идеи?


person alessandro308    schedule 01.02.2018    source источник
comment
Вы пытались использовать buffer.compact() после buffer.flip()? Признаюсь, я не слишком внимательно прочитал ваш код...   -  person zlakad    schedule 01.02.2018


Ответы (1)


Правильный способ написания этого цикла копирования выглядит следующим образом:

while (in.read(buffer) >= 0 || buffer.position() > 0)
{
    buffer.flip();
    out.write(buffer);
    buffer.compact();
}

Если боковое чтение из канала сокета никогда не выходит из этого цикла, одноранговый узел не закрыл соединение.

person user207421    schedule 01.02.2018