2013-04-25 3 views
0

Моя цель - отправить различные сообщения от клиента на сервер, и он будет основан на тексте. То, что я не уверен, - это то, как del с частичным чтением здесь. Я должен быть уверен, что получаю целую новость и ничего больше.Java nio partial read

У кого-нибудь есть опыт?

Вот то, что я до сих пор:

private void handleNewClientMessage(SelectionKey key) throws IOException { 
    SocketChannel sendingChannel = (SocketChannel) key.channel(); 

    ByteBuffer receivingBuffer = ByteBuffer.allocate(2048); 
    int bytesRead = sendingChannel.read(receivingBuffer); 
    if (bytesRead > 0) { 
     receivingBuffer.flip(); 

     byte[] array = new byte[receivingBuffer.limit()]; 
     receivingBuffer.get(array); 
     String message = new String(array); 

     System.out.println("Server received " +message);   
    } 
    selector.wakeup(); 
} 

Но у меня нет никакого способа «окончание» сообщение и быть уверенным, чтобы иметь одно полное сообщение.

С наилучшими пожеланиями, O

+0

Вы должны добавить свой текстовый протокол поверх сокета. Как и HTTP. – Nikolai

+0

Hi @Nikolai. Это звучит хорошо, у вас есть ссылка на какой-то пример здесь? Ура! – olemara

+0

HTTP является фактическим примером. Вы можете использовать библиотеку HttpComponents для анализа HTTP-протокола. – Nikolai

ответ

3

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

Вместо этого я прочитал бы столько, сколько вы можете, в ByteBuffer, а затем проанализируйте его, чтобы найти конец сообщения, например. новая строка для текста.

Когда вы найдете конец строки, извлеките его и преобразуйте в String и обработайте. повторите, пока у вас не будет частичного сообщения (или ничего не осталось)

Если вы обнаружили, что у вас есть только часть сообщения, вы компактно() (если position()> 0), когда у вас есть, и попробуйте прочитать() еще несколько ,

Это позволит вам читать как можно больше сообщений одновременно, но может также обрабатывать неполные сообщения.

Примечание: вам необходимо сохранить ByteBuffer для подключения, чтобы вы знали, какие частичные сообщения вы прочитали раньше.

Примечание: это не будет работать, если у вас есть сообщение, размер которого больше размера вашего буфера. Я предлагаю использовать переработанный прямой ByteBuffer, скажем, 1+ МБ. С помощью ByteBuffers только страницы используемого ByteBuffer выделяются для реальной памяти.

Если вы беспокоитесь об эффективности, я бы воспользовался вашим byte[], где это было возможно. Вам нужно только перераспределить его, если вам нужно больше места, чем вы уже сделали.

BTW, вы можете найти, используя BufferedReader с Plain IO, намного проще в использовании, но все же производительность достаточно хорошо.

+0

Привет @Peter_Lawrey, спасибо за хорошее объяснение. Я попытаюсь реализовать этот подход. – olemara