小编典典

简单的Java HTTP客户端无服务器响应

java

我正在尝试编写一个简单的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”-即使为true,它仍会挂起。


阅读 346

收藏
2020-11-26

共1个答案

小编典典

我认为我可以通过对代码进行少量更改来重现该问题,因此现在它在我的计算机上不起作用,并且表现出与您的环境相同的行为。我只是将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());

至少,通过这些更改,我也可以确认程序可以在我的机器上正常工作。

2020-11-26