1

I'm attempting to write a simple Java http client that simply prints out one line of the server response. My problem is that I get no response from the server. Here is what I have, which is compiling and running with no explicit errors, it just hangs after I type a hostname, e.g. '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());

        }
    }   
}

Any suggestions? Note that this assumes an 'index.html' exists - it still just hangs even if this is true.

  • 1
    Use a debugger to see where you code is hanging. – Hiro2k Mar 31 '12 at 20:52
  • I know the out.println("GET /index.html HTTP/1.0\n"); goes out but System.out.println("Response from "+line+": "+in.readLine()); never gets called. –  Mar 31 '12 at 21:00
  • 1
    Works for me. I get: `Response from www.google.com: HTTP/1.0 302 Found`. – Giulio Piancastelli Mar 31 '12 at 21:02
  • Really? Does it make a difference if I am doing this from the main method or not? I currently am...you're using the exact code above? –  Mar 31 '12 at 21:04
  • @gonzoc0ding I am using the code above from within a `main` method. I have just elided the `try`/`catch` block in favor of letting the method throw an exception. I also added the `line` declaration. – Giulio Piancastelli Mar 31 '12 at 21:06
  • @GiulioPiancastelli I don't see how this is possible! I updated the code above with my full program. If you throw this in a file called DNSTest.java, and run it, it works? What could be the difference? –  Mar 31 '12 at 21:10
  • @gonzoc0ding yes it works. Alas, I don't have any suggestions ready as to understand why it hangs on your part. Except that the way you name your class or file is unlikely to play a role in it. – Giulio Piancastelli Mar 31 '12 at 21:16

3 Answers3

3

I think I have been able to reproduce the problem by applying a small change to the code, so now it doesn't work on my machine and exhibits the same behavior as it does in your environment. I just changed the out.println call to a simpler out.print, and lo and behold, the program hangs after sending out the request but before the last println call.

As far as I can remember, HTTP requests need to supply an empty line after the headers, where the line separator must be the \r\n couple of characters. I suppose that your environment is such that println does not send the correct line separators (you can check the value of System.getProperty("line.separator") to verify which are the ones used on your system), so the request is interpreted by the server as incomplete and you get nothing on the input side. Some servers are quite forgiving and accept just \n as line separator, but if you happen to send \n explicitly and \r\n implicitly (by means of println) then your supposedly empty line contains the \r character and is no more seen as empty, possibly faulting the request to the effect of preventing the server to send back any response.

Therefore, my advice is to use print and send the correct line separators explicitly. Also, you very probably need to add a call to flush, maybe because there's an empty line in between the output - I don't really know, but without invoking flush my program still hangs. So, to sum up, the following should work:

// 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());

At least, I can confirm the program works on my machine with these changes, too.

Giulio Piancastelli
  • 15,368
  • 5
  • 42
  • 62
2

I recommend to make

  out.flush();

after out.println(...);

This will send the data to the remote server. It looks like the data never leaves your local buffer.

I.e.

        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());

And if I type google.com it gives me:

 Response from google.com: HTTP/1.0 200 OK

If it doesn't work, try this:

        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

Note, the URL should be like "http://google.com" not just "google.com"

Eugene Retunsky
  • 13,009
  • 4
  • 52
  • 55
  • Still no go - just hangs after I type 'www.google.com' and hit enter. I can't figure it out. –  Mar 31 '12 at 21:31
  • Using your exact code above results in a hang still. What could be different between our environments? I have no firewall (that I'm aware of) and am just running OSX... –  Mar 31 '12 at 21:36
  • Are you sure it hangs? If you add any other System.out.println (e.g. right before out.pringln("GET... ) - do you see what it prints? – Eugene Retunsky Mar 31 '12 at 21:40
  • I see printlns all the way up until I try to read one line of server response: System.out.println("Response from "+line+": "+in.readLine()); E.g. If I print something right before this last line, I see it. –  Mar 31 '12 at 21:47
  • Further, if I remove the "+in.readLine()" from the last line of the program, it shows "Response from www.google.com: ". –  Mar 31 '12 at 21:48
  • Gotcha. Try the block of code I just added. Let me know if it works or not. – Eugene Retunsky Mar 31 '12 at 21:50
  • That worked. But I'm technically supposed to be using the manual method of opening a second and sending the request myself, as its for a project. I can't figure out why my code would work for you and not me other than environment. –  Mar 31 '12 at 22:03
  • Really hard to say as long as your method works for me. I would try to read the InputStream directly - i.e. read bytes from the response, and see where it fails. – Eugene Retunsky Mar 31 '12 at 22:12
0

I had exactly the same behavior when i tried the code of the 1st post (on Windows 8). Same thing with all the others ways suggested in this topic.

Then I unninstalled my Antivirus (avast) and everything worked... :$

Anthony Bobenrieth
  • 2,758
  • 1
  • 26
  • 38