URL-адрес объектов Inputstream и outputstream

это мой код

URL url = new URL("http://172.16.32.160:8080/epramaan/loginotp");
URLConnection connection1 = url.openConnection();
connection1.setDoOutput(true);

ObjectOutputStream out=new ObjectOutputStream(connection1.getOutputStream());
out.writeObject(send);
out.flush();
out.close();

ObjectInputStream in = new ObjectInputStream(connection1.getInputStream());
String output=(String)in.readObject();
in.close();

//Rest of the code

Как только OutputStream запишет данные в поток, остановит ли объект InputStream выполнение до тех пор, пока не будет получен ответ?


person suraj    schedule 13.03.2012    source источник
comment
Вы должны открыть входной поток перед отправкой каких-либо данных, чтобы убедиться, что вы получите все, что вам нужно от сервера.   -  person Michael Laffargue    schedule 13.03.2012
comment
Вы имеете в виду, что перед отправкой данных с помощью out.writeObject() я должен инициализировать объект inputStream? Не могли бы вы уточнить   -  person suraj    schedule 13.03.2012
comment
@MichaelLaffargue - На самом деле, я не думаю, что это необходимо. HTTP 1.1 RFC говорит следующее: После получения и интерпретации сообщения запроса сервер отвечает ответным сообщением HTTP.. (раздел 6). Оперативное слово после. Сервер, который начал отправлять ответ, все еще читая запрос, будет нарушать спецификацию. Следовательно, нет необходимости открывать входной поток, пока выходной поток не будет закрыт.   -  person Stephen C    schedule 13.03.2012
comment
@StephenC Возможно, вы правы в отношении HTTP-обмена, но я считаю хорошей практикой подготовиться к получению данных перед запуском всего процесса записи/чтения.   -  person Michael Laffargue    schedule 13.03.2012
comment
@MichaelLaffargue: Вы имеете в виду, что мы должны инициализировать объект входного потока перед отправкой каких-либо данных? Потому что иногда я, кажется, получаю java.io.StreamCorruptedException при использовании нескольких потоков ввода и вывода объектов (отправляется только строка). Так поможет ли открытие входного потока перед отправкой каких-либо данных?   -  person Ashwin    schedule 13.03.2012
comment
@ user1139023 - нет, не поможет.   -  person Stephen C    schedule 14.03.2012


Ответы (3)


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

Только что заметил, что вы используете readObject, а не читаете. Пожалуйста, уточните, какие данные вы читаете/записываете и почему вы используете потоки объектов?

Как вы упомянули, что используете String, я бы предложил использовать метод readFully(byte[] buf). Этот метод блокируется до тех пор, пока не будут прочитаны все байты. Получив массив байтов, Строка может быть создана из этого массива байтов.

person Santosh    schedule 13.03.2012
comment
Вопрос заключается в использовании readObject(), а не read(). API readObject() не определяет блокировку - person Oded Peer; 13.03.2012
comment
@Santosh: я использую данные String - person suraj; 13.03.2012
comment
@Santosh: А как насчет метода readObject()? Это также блокируется до тех пор, пока весь объект не будет прочитан. Потому что я, кажется, получаю (иногда) java.io.StreamCorruptedException при использовании нескольких потоков ввода и вывода объектов. - person Ashwin; 13.03.2012
comment
@user1139023 user1139023, когда вы читаете объект Java с помощью ObjectInputstream, он следует собственному протоколу, специфичному для объектов Java. Он ожидает определенных вещей в определенном формате и порядке. То, что вы делаете, это чтение с URL-адреса, который имеет совершенно другой протокол, то есть HTTP. Собственный поток объектов Java не может его понять, поэтому вы получаете java.io.StreamCorruptedException. - person Santosh; 14.03.2012
comment
@Santosh: Тогда почему бы мне не получать StreamCorruptedException каждый раз. Не могли бы вы дать подробный ответ в разделе ответов, чтобы было легко принять или проголосовать за ваш ответ. - person Ashwin; 14.03.2012
comment
@Santosh: HTTP — это транспортный уровень, который не имеет ничего общего с двоичным содержимым. По протоколу HTTP вы получаете текстовое (HTML) и двоичное содержимое, такое как изображения, файлы PDF и т. д. Клиент, выполняющий запрос, знает, как читать данные в ответе, обычно это определяется в заголовке Content-Type. - person Oded Peer; 14.03.2012
comment
@OdedPeer, я понял, спасибо, что указали на это. я имел в виду, что в некоторых случаях (что происходит здесь нечасто) некоторые данные теряются при передаче, и, следовательно, readObject() не может восстановить объект обратно. Для содержимого, такого как PDF/изображения, в случае потери данных они все равно будут отображаться браузерами, хотя и с некоторыми ошибками. - person Santosh; 14.03.2012

Вы можете использовать InputStream.read(byte[]) для чтения всего массива байтов в память (вы можете получить длину массива из заголовка HTTP Content-Length) и использовать URLConnection.setReadTimeout() для истечения времени ожидания, если вы блокируете слишком долго.
Из массива байтов вы можете создать свой объект, создав свой ObjectInputStream поверх ByteArrayInputStream.

person Oded Peer    schedule 13.03.2012
comment
Почему я получаю исключение java.io.CorruptedStreamException при использовании нескольких потоков ввода-вывода? Я закрыл все объекты InputStream и Object Output Stream тут и там. Эта ошибка возникает не всегда. Она возникает только в первый раз, когда я нажимаю кнопку. (Кнопка onClickListener содержит код для отправки и получения) - person suraj; 14.03.2012
comment
Что вы подразумеваете под множественным потоком объектов ввода-вывода? Я не вижу нескольких экземпляров в коде вашего вопроса. - person Oded Peer; 14.03.2012

Как только OutputStream запишет данные в поток, остановит ли объект InputStream выполнение до тех пор, пока не будет получен ответ?

Не совсем. Открытие InputStream ничего не блокирует и даже не вызывает отправку заголовков запроса. Однако чтение из InputStream сделает обе эти вещи.

Я подозреваю, что настоящая причина ваших проблем заключается в том, что вы получаете ответ об ошибке от сервера, который является чем-то другим, чем сериализованный объект; например это может быть общая HTML-страница с ошибкой с сервера. Естественно, попытка десериализовать это терпит неудачу.

Правильная процедура:

  1. Создайте объект URLConnection.
  2. Установите любые заголовки запроса, которые вам нужны.
  3. Подключите его (или пропустите это... это произойдет неявно).
  4. Откройте и напишите в OutputStream.
  5. Закройте выходной поток.
  6. Use getResponseCode() to see if the request succeeded or failed.
    1. If it succeeded, call getInputStream() and read and process the response.
    2. Если это не удалось, вызовите getErrorStream() и обработайте вывод ошибки.
person Stephen C    schedule 14.03.2012
comment
У меня такая же проблема, как и у пользователя 1166690. Поэтому я задаю вопрос, который он задал Одеду сверстнику. Почему я получаю исключение java.io.CorruptedStreamException при использовании нескольких потоков ввода-вывода? Я закрыл все объекты InputStream и Object Output Stream тут и там. Эта ошибка возникает не всегда. Она возникает только в первый раз, когда я нажимаю кнопку. (Кнопка onClickListener содержит код для отправки и получения) - person Ashwin; 14.03.2012