2015-04-10 5 views
1

Я разрабатываю небольшое приложение терминала, которое обрабатывает взаимодействия с сервером POP3. Тем не менее, у меня проблема, когда read() и readLine() из блока BufferedReader. Мои первоначальные попытки использовали readLine(), но после чтения на SO и других сайтах я понял, что сервер не возвращает соответствующие символы, чтобы отметить конец строки, поэтому я попытался использовать read(). Но по какой-то причине это блокирует также.BufferedReader read() и readLine() оба висят, пытаясь получить ответ с сервера POP3

Socket s = new Socket(InetAddress.getByName(this.HOST), 110); 

    BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); 
    PrintWriter out = new PrintWriter(s.getOutputStream(), true); 

    String res = in.readLine(); // This works fine 
    System.out.println(res); 

    res = ""; 
    char [] charRes = new char[1024]; 

    out.println("USER " + this.username); 
    // res = in.readLine(); 
    in.read(charRes); // Does not work 
    res = charRes.toString(); 
    System.out.println(res); 

Проблема не с сервером, потому что я тестировал его с помощью Telnet и она отлично работает. Я не уверен, что я делаю неправильно, и я был бы признателен за любую помощь.

Мое клиентское программное обеспечение работает в системе Linux, и я подключаюсь к серверу Windows.

+0

Почему вы не используете JavaMail? – EJP

+0

Это практическое задание для класса сетей. Я не могу использовать ничего, кроме сокетов. – user3493992

ответ

0

Согласно the documentation, метод read(byte[]) будет блокироваться, пока по меньшей мере один байт не будет считан из потока.

Чтобы обеспечить доступность данных до вызова метода read(byte[]), вы можете позвонить по методу available(), documented here.

Основываясь на вашем исходном вопросе и последующих комментариях, основная проблема, по-видимому, вызвана окончанием строки. Вы указали, что клиент работает в Linux, где стандартная строка заканчивается LF (\n), но POP3 RFC специально требует, чтобы каждая команда была завершена CRLF (\r\n). Вместо использования out.println() (который автоматически использует системную строку, заканчивающуюся \n), попробуйте использовать метод PrintWriter.write(String) (documentation).

Возможно, вы используете конструктор PrintWriter с номером autoFlush равным true. Это означало, что ваш поток будет автоматически очищаться при использовании метода println(), ОДНАКО, он не будет автоматически сбрасываться при использовании метода write(), поэтому вам также необходимо будет добавить вызов flush(). Опять же, рекомендуется обратиться к the documentation. Обновленный код будет выглядеть примерно так:

out.write("USER " + this.username + "\r\n"); 
out.flush(); 

Вы можете рассмотреть аналогично обновлению вашего считывает из входного потока, чтобы убедиться, что вы не должны вручную удалить \r символы из входного (различные методы readLine() будет потреблять/отбрасывать \n, но не \r, когда клиент работает на Linux).

+0

Спасибо за ответ. Я попробовал flush(), а также (s.getInputStream()). Available(), который возвращает 0 (что, конечно же, означает, что он достиг конца входного потока). Я даже пытался in.ready(), который возвращает false. Я не понимаю, почему это так. Я знаю, что я не отправляю неверный запрос на сервер, потому что я скопировал его в терминал, и это сработало, поэтому я предполагаю, что это может не привести к правильному завершению запроса. Как мне это исправить? – user3493992

+0

Чтобы быть понятным, вы выполняете 'out.flush()' правильно? Что касается завершения запроса, [POP3 RFC] (http://tools.ietf.org/html/rfc1939#section-3) специально требует, чтобы каждая команда была завершена CRLF, но когда вы вызываете 'out. println() 'строка будет прервана либо LF, либо CRLF в зависимости от платформы/архитектуры. – user700390

+0

Я замечаю, что вы используете конструктор 'PrintWriter' с' autoFlush', установленным в 'true', поэтому я не думаю, что ваша проблема будет вызвана сбоем потока вывода. Окончательные строки кажутся наиболее вероятным виновником на этом этапе. – user700390