2011-12-15 7 views
1

В стороне клиента, прочитать код:ява NiO SocketChannel читать всегда возвращают те же данные

byte[] bytes = new byte[50]; //TODO should reuse buffer, for test only 
ByteBuffer dst = ByteBuffer.wrap(bytes); 
int ret = 0; 
int readBytes = 0; 
boolean fail = false; 
try { 
    while ((ret = socketChannel.read(dst)) > 0) { 
    readBytes += ret; 
    System.out.println("read " + ret + " bytes from socket " + dst); 
    if (!dst.hasRemaining()) { 
     break; 
    } 
    } 
    int pos = dst.position(); 
    byte[] data = new byte[pos]; 
    dst.flip(); 
    dst.get(data); 
    System.out.println("read data: " + StringUtil.toHexString(data)); 
} catch (Exception e) { 
    fail = true; 
    handler.onException(e); 
} 

Проблема заключается в socketChannel.read() всегда возвращает положительный, я проверил обратный буфер, данные дублирующие N раз, ему нравится, что позиция буфера сокета низкого уровня не движется вперед. Есть идеи?

ответ

-2

1: Это может быть не ошибка!

[при условии, что есть машиночитаемые данные в буфере] ...

Вы ожидали бы, что -1 в конце потока ... Просмотреть http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/channels/SocketChannel.html#read%28java.nio.ByteBuffer%29

Если вы постоянно ПОЛУЧАТЬ положительное значение из вызова read(), тогда вам нужно будет определить, почему данные постоянно читаются.

Конечно, тайна здесь в конечном счете лежит в исходных данных (т. Е. SocketChannel, из которого вы считываете данные).

2: Объяснение ваших возможных проблем

Если сокет канала поступает из РЕАЛЬНОГО файла, который является конечным, то ваш файл действительно большой, и в конце концов, операция чтения() вернет 0. .. в конце концов ...

Если, с другой стороны, ваш сокет-канал прослушивает источник данных, который вы EXPECT, чтобы быть конечным (например, сериализованный поток объектов, например), я бы дважды проверял источник --- Возможно, ваш конечный поток просто производит все больше и больше данных ... и вы правильно его потребляете.

3: Наконец, некоторые советы

Трюк для отладки такого рода ошибок играет с входом ByteBuffer на ваш метод чтения: Хорошая вещь о ByteBuffers java.nio является то, что, так как они более объект ориентированные, а затем более старые байтовые [] писатели, вы можете получить очень тонкую отладку своих операций.

+0

Спасибо за ваш быстрый повтор. Это канал сокета, подключаемый к серверу Netty. Я отправляю один запрос на сервер, сервер возвращает всего 48 байт, код выполняется только тогда, когда selector.select() return и selectionKey читается. Поэтому я полностью смутился. –

+0

BTW, как я упоминал в заголовке, то, что я читал из socketChannel, это возврат 48 байтов с сервера, проблема в том, что я всегда могу прочитать те же данные из socketChannel. И поскольку данные верны, поэтому я могу их декодировать, поэтому это никогда не останавливается :-( –

+0

Таким образом --- это не ошибка в вашем коде. Можете ли вы уточнить, какие данные вы читаете из Netty? – jayunit100

0

Если сервер только вернул 48 байтов, ваш код должен быть заблокирован в методе read(), пытаясь получить 49-й и 50-й байты. Таким образом, либо ваш «50» ошибочен, либо вам придется реструктурировать свой код, чтобы читать и обрабатывать все, что вы получаете по мере его получения, а не пытаться сначала заполнить буферы. И это не может быть код, в котором вы думаете, что у вас всегда есть одни и те же данные. Объяснением для этого было бы неспособность сжать буфер после get, если вы повторно используете тот же буфер для следующего чтения, который вы должны сделать, но ваш опубликованный код не делает.