Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Пара вопросов по java.nio


Автор: untied 13.7.2010, 08:36
Приветствую.

Сразу скажу, что туториалы и примеры по java.nio (в т.ч. The Rox Java NIO) я читал. Интересует следующее:

1. Во всех туториалах предполагается, что размер принимаемого сервером пакета заведомо меньше размера буфера. Соответственно разик прочитали в буфер, получили пакет. А что делать, если размер пакета может быть больше размера буфера? Допустим, кто-то шлет файло на несколько мегабайт. Как это склеивать?

2. Как отслеживать таймаут? Допустим, прочитали в буфер, отослали этот буфер в поток-склеиватель пакетов. Как прекратить сборку пакета, если превышено время ожидания?

Автор: Kircul 13.7.2010, 10:09
Можно сразу пример кода, который не понравился?

Автор: untied 13.7.2010, 10:33
Ну почему не понравился? Мне все нравится. Просто найденные примеры не годятся для моей задачи.

__h t t p : / / rox-xmlrpc.sourceforge.net/niotut/
__h t t p : / / habrahabr.ru/blogs/java/70690/

В обоих примерах предполагается, что размер входящего пакета меньше размера буфера. Соответственно, одно чтение -- один пакет, таймаут не нужен.

У меня размер входного пакета может быть несколько мегабайт (до сотни). Делать буфер такого размера нерентабельно (да Java и не даст). Соответственно, пакет нужно собирать по кускам. Но как?

Автор: Kircul 13.7.2010, 11:13
Исходя из кода http://rox-xmlrpc.sourceforge.net/niotut/src/NioClient.java, метод read нужно модифицировать примерно так:
Код

         private void read(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();

        // Clear out our read buffer so it's ready for new data
        this.readBuffer.clear();

        // Attempt to read off the channel
        int numRead;
        try {
                        while ((numRead = socketChannel.read(this.readBuffer)) != -1) {
                              // Handle the response
                      this.handleResponse(socketChannel, this.readBuffer.array(), numRead);                
                }
                        // Remote entity shut the socket down cleanly. Do the
            // same from our end and cancel the channel.
            key.channel().close();
            key.cancel();
            return;
        } catch (IOException e) {
            // The remote forcibly closed the connection, cancel
            // the selection key and close the channel.
            key.cancel();
            socketChannel.close();
            return;
        }
        
    }

Как-то так оно должно принять полный пакет.

Автор: COVD 13.7.2010, 16:45
Цитата

предполагается, что размер принимаемого сервером пакета заведомо меньше 


Вовсе нет. Данные из сети  поступают любыми порциями, но в буфер за один раз будет прочитано не больше, чем там (в буфере) есть свободного места.  

http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/api/java/nio/channels/SocketChannel.html#read(java.nio.ByteBuffer)
Цитата

public abstract int read(ByteBuffer dst)
...
An attempt is made to read up to r bytes from the channel, where r is the number of bytes remaining in the buffer


Вообще, если мало (сотни) клиентов обмениваются с сервером большими обьемами данних, то возможно проще и эффективнее использовать IO (один клиент - один блокируюший поток). NIO (много клиентов - один неблокируюший поток) выгоден, когда много (тысячи) клиентов эпизодически (т.е. со значительными паузами) обмениваются мелкими порциями данных.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)