Простой Java-клиент http не отвечает серверу - PullRequest
1 голос
/ 01 апреля 2012

Я пытаюсь написать простой Java-http-клиент, который просто выводит одну строку ответа сервера. Моя проблема в том, что я не получаю ответ от сервера. Вот что у меня есть, которое компилируется и запускается без явных ошибок, просто зависает после ввода имени хоста, например 'Www.google.com':

import java.io.*;
import java.net.*;

public class DNSTest {
    // Constructor
    public DNSTest() { }

    // Builds GET request, opens socket, waits for response, closes
    public static void main(String[] args) throws Exception{
        String line;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        //For each hostname
        while ((line = br.readLine()) != null){ 
            //Resolve the hostname to an IP address
            InetAddress ip = InetAddress.getByName(line);

            //Open socket on ip address
            Socket socket = new Socket(ip, 80);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            //Send request
            out.println("GET /index.html HTTP/1.0\n");

            //Read one line of input
            System.out.println("Response from "+line+": "+in.readLine());

        }
    }   
}

Есть предложения? Обратите внимание, что предполагается, что существует index.html - он все равно просто зависает, даже если это так.

Ответы [ 3 ]

3 голосов
/ 01 апреля 2012

Я думаю, что смог воспроизвести проблему, применив небольшое изменение к коду, поэтому теперь он не работает на моей машине и демонстрирует то же поведение, что и в вашей среде.Я просто изменил out.println вызов на более простой out.print, и вот, программа зависает после отправки запроса, но до последнего println вызова.

Насколько я помню, HTTP-запросы должны содержать пустую строку после заголовков, где разделитель строк должен быть парой символов \r\n.Я предполагаю, что ваша среда такова, что println не отправляет правильные разделители строк (вы можете проверить значение System.getProperty("line.separator"), чтобы проверить, какие из них используются в вашей системе), поэтому запрос интерпретируется сервером как неполныйи вы ничего не получите на стороне ввода.Некоторые серверы довольно просты и принимают только \n в качестве разделителя строк, но если вам случится отправить \n явно и \r\n неявно (с помощью println), то ваша предположительно пустая строка содержит символ \r ибольше не рассматривается как пустой, что может привести к сбою в запросе, из-за чего сервер не может отправлять обратно любой ответ.

Поэтому я советую использовать print и явно отправлять правильные разделители строк.Кроме того, очень вероятно, что вам нужно добавить вызов к flush, возможно, потому, что между выводом есть пустая строка - я не знаю, но без вызова flush моя программа все еще зависает.Итак, чтобы подвести итог, должно работать следующее:

// send request
out.print("GET /index.html HTTP/1.0\r\n\r\n");
out.flush();
// read one line of input
System.out.println("Response from " + line + ": " + in.readLine());

По крайней мере, я могу подтвердить, что программа работает на моем компьютере и с этими изменениями.

2 голосов
/ 01 апреля 2012

Рекомендую сделать

  out.flush();

после out.println (...);

Это отправит данные на удаленный сервер. Похоже, данные никогда не покидают ваш локальный буфер.

т.е.

        Socket socket = new Socket(ip, 80);
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(
            new InputStreamReader(socket.getInputStream()));

        //Send request
        out.println("GET /index.html HTTP/1.0\n");
        out.flush();

        //Read one line of input
        System.out.println("Response from "+line+": "+in.readLine());

И если я наберу google.com, это даст мне:

 Response from google.com: HTTP/1.0 200 OK

Если это не работает, попробуйте это:

        HttpURLConnection connection = (HttpURLConnection) 
            new URL(url).openConnection();
        connection.setRequestMethod("GET");
        connection.setDoInput(true);
        connection.setDoOutput(false);
        connection.setUseCaches(false);
        connection.setRequestProperty("Accept", "text/html");
        final InputStream is = connection.getInputStream();
        // construct BufferredStreamReader from the is

Обратите внимание, что URL должен быть похож на "http://google.com", а не просто" google.com "

0 голосов
/ 01 января 2013

У меня было точно такое же поведение, когда я попробовал код 1-го поста (на Windows 8).То же самое со всеми другими способами, предложенными в этом разделе.

Затем я удалил свой антивирус (avast), и все заработало ...: $

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...