Чтение сокетов Java - либо получение повторяющихся строк, либо потеря - PullRequest
0 голосов
/ 09 марта 2011

У меня полевой день, чтобы выяснить, почему мой Java-код не работает.

Я должен получать следующие сообщения от C-программы через сокеты.

1 ~ сообщение ~ я люблю тебя \ r \ n
2 ~ сообщение ~ ты меня любишь? \ R \ n 3 ~ сообщение ~ когда мы встретимся снова? \ R \ n 4 ~ сообщение ~ Как насчетсейчас? \ r \ n 5 ~ сообщение ~ О!Я беременна! \ R \ n

Вместо этого я получаю следующие сообщения.

1 ~ сообщение ~ я люблю тебя \ r \ n 2 ~сообщение ~ ты меня любишь? \ r \ n 2 ~ сообщение ~ ты меня любишь? \ r \ n 5 ~ сообщение ~ О!Я беременна! \ R \ n

Я запустила перенаправление портов на своем ноутбуке и обнаружила, что программа C передает сообщения правильно.Это моя программа на Java, которая не получает их должным образом.

Я использую Java NIO Channels для получения сообщений.

Мой код выглядит следующим образом:

StringBuffer stringBuffer = new StringBuffer();
int pos = 0;     // position of Buffer

// initialize server and client sockets
ServerSocketChannel serverChannel = null;
SocketChannel clientChannel = null;

// initialize ByteBuffer
ByteBuffer inBuffer = ByteBuffer.allocateDirect(65536);
inBuffer.order(ByteOrder.LITTLE_ENDIAN);

try {
   serverChannel = ServerSocketChannel.open();
   SocketAddress port = new InetSocketAddress(8080);
   serverChannel.socket().bind(port);

      while (true) {
         clientChannel = serverChannel.accept();

         while ((bytesRead = clientChannel.read(inBuffer)) != -1) {

            inBuffer.flip();

               while (inBuffer.get(pos) != '\r') {

                  stringBuffer.append((char) inBuffer.get(pos));
                  pos++;

               } // end while loop checking for bytesRead

               //increment over \r and \n
               inBuffer.get();
               bytesRead--;
               inBuffer.get();
               bytesRead--;
               pos = pos + 2;

               System.out.println(stringBuffer);
               stringBuffer.setLength(0);
               pos = 0;

           } // close while reading bytesRead loop

      } // close while(true) loop
} catch (IOException ex) {
}

Ответы [ 3 ]

1 голос
/ 09 марта 2011

У вас есть , чтобы использовать NIO для этого? Как правило, гораздо сложнее получить права (по крайней мере, для меня). Я предполагаю, что проблема в том, что вы всегда читаете, но вы вызываете flip ровно один раз за чтение ... тогда как я ожидал бы увидеть два сальто или, возможно, сальто перед read, а затем clear в конце обработки.

Обратите внимание, что вы также полностью игнорируете bytesRead - зачем уменьшать значение переменной, которую вы затем переназначаете, не читая?

Кроме того, вы предполагаете, что получаете точно один \r с каждого read вызова. Что если вы получите две строки за один вызов или одну неполную линию?

Я не квалифицирован, чтобы дать правильный код NIO, но я бы порекомендовал вам попытаться заставить его работать сначала с простым InputStream, а затем , а затем перейти на NIO.

0 голосов
/ 09 марта 2011

Я предлагаю вам попробовать простой ввод-вывод, который проще для этого варианта использования.

ServerSocket serverSocket = new ServerSocket(8080);
while(!serverSocket.isClosed()) {
    Socket socket = serverSocket.accept();
    System.out.println("Accepted socket "+socket);
    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
    StringBuilder sb = new StringBuilder();
    int b;
    while((b = bis.read())>=0) {
        if (b == '\r')
            b = bis.read();
        if (b == '\n') {
            System.out.println(sb);
            sb.setLength(0);
        } else {
            sb.append((char) b);
        }
    }
    System.out.println("Closing socket.");
    socket.close();
}
0 голосов
/ 09 марта 2011
  • SocketChannel.read помещает данные в буфер в текущей позиции буфера . Вы итерируете буфер из позиции 0 каждый раз.
  • Если вы получаете две строки в одной read, вы обрабатываете только до первого \ r, а затем продолжаете читать снова. Таким образом, вы можете пропустить последние строки.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...