Невозможно записать выход после считывания ввода

Я пишу программу, которая подключается к сервлету с помощью HttpURLConnection, но я застрял при проверке URL

public void connect (String method) throws Exception {

server = (HttpURLConnection) url.openConnection ();
server.setDoInput (true);
server.setDoOutput (true);
server.setUseCaches (false);
server.setRequestMethod (method);
server.setRequestProperty ("Content-Type", "application / xml");

server.connect ();

/*if (server.getResponseCode () == 200)
{
System.out.println ("Connection OK at the url:" + url);
System.out.println ("------------------------------------------- ------- ");
}
else
System.out.println ("Connection failed"); 

}*/

Я получил ошибку:

java.net.ProtocolException: не удается записать вывод после чтения.

если я проверяю URL с кодом в комментариях, но он отлично работает без него к сожалению, мне нужно проверить URL-адрес, поэтому я думаю, что проблема исходит из метода getResponseCode, но я не знаю, как его разрешить.

Большое спасибо

Ответ 1

Протокол HTTP основан на шаблоне запроса-ответа: сначала вы отправляете запрос, а сервер отвечает. Как только сервер ответил, вы не можете отправлять больше контента, это не имеет смысла. (Как сервер дал вам код ответа до, он знает, что вы пытаетесь отправить?)

Поэтому, когда вы вызываете server.getResponseCode(), вы фактически сообщаете серверу, что ваш запрос завершен, и он может его обработать. Если вы хотите отправить больше данных, вам необходимо запустить новый запрос.

Глядя на свой код, вы хотите проверить, было ли само соединение успешным, но нет необходимости в этом: если соединение не удалось, Exception вызывается server.connect(). Но результат попытки подключения не совпадает с кодом ответа HTTP, который всегда возникает после того, как сервер обработал все ваши данные.

Ответ 2

Я думаю, что исключение не связано с printing url. Там должен быть какой-то фрагмент кода, который пытается записать, чтобы установить тело запроса после чтения ответа.

Это исключение произойдет, если вы попытаетесь получить HttpURLConnection.getOutputStream() после получения HttpURLConnection.getInputStream()

Вот пример использования sun.net.www.protocol.http.HttpURLConnection.getOutputStream:

public synchronized OutputStream getOutputStream() throws IOException {

     try {
         if (!doOutput) {
             throw new ProtocolException("cannot write to a URLConnection"
                            + " if doOutput=false - call setDoOutput(true)");
         }

         if (method.equals("GET")) {
             method = "POST"; // Backward compatibility
         }
         if (!"POST".equals(method) && !"PUT".equals(method) &&
             "http".equals(url.getProtocol())) {
             throw new ProtocolException("HTTP method " + method +
                                         " doesn't support output");
         }

         // if there already an input stream open, throw an exception
         if (inputStream != null) {
             throw new ProtocolException("Cannot write output after reading 
                input.");
         }

         if (!checkReuseConnection())
             connect();

         /* REMIND: This exists to fix the HttpsURLConnection subclass.
          * Hotjava needs to run on JDK.FCS.  Do proper fix in subclass
          * for . and remove this.
          */

         if (streaming() && strOutputStream == null) {
             writeRequests();
         }
         ps = (PrintStream)http.getOutputStream();
         if (streaming()) {
             if (strOutputStream == null) {
                 if (fixedContentLength != -) {
                     strOutputStream = 
                        new StreamingOutputStream (ps, fixedContentLength);
                 } else if (chunkLength != -) {
                     strOutputStream = new StreamingOutputStream(
                         new ChunkedOutputStream (ps, chunkLength), -);
                 }
             }
             return strOutputStream;
         } else {
             if (poster == null) {
                 poster = new PosterOutputStream();
             }
             return poster;
         }
     } catch (RuntimeException e) {
         disconnectInternal();
         throw e;
     } catch (IOException e) {
         disconnectInternal();
         throw e;
     }
 }

Ответ 3

У меня была та же проблема. Решение проблемы состоит в том, что вам нужно использовать последовательность

openConnection -> getOutputStream -> write -> getInputStream -> read

Это означает..:

public String sendReceive(String url, String toSend) {
URL url = new URL(url);
URLConnection conn = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.sets...

OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(toSend);
out.close();

BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String receive = "";
do {
    String line = in.readLine();
    if (line == null)
        break;
    receive += line;
} while (true);
in.close();

return receive;
}

String results1 = sendReceive("site.com/update.php", params1);
String results2 = sendReceive("site.com/update.php", params2);
...

Ответ 4

У меня тоже есть эта проблема, меня удивляет то, что ошибка вызвана моим добавленным кодом System.out.println(conn.getHeaderFields());

Ниже мой код:

HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
configureConnection(conn);
//System.out.println(conn.getHeaderFields()); //if i comment this code,everything is ok, if not the 'Cannot write output after reading input' error happens
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(paramsContent.getBytes());
os.flush();
os.close();