我正在尝试编写一个简单的 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”——即使这是真的,它仍然只是挂起。
最佳答案
我想我已经能够通过对代码进行小的更改来重现该问题,所以现在它在我的机器上不起作用并且表现出与在您的环境中相同的行为。我只是将 out.println
调用更改为更简单的 out.print
,你瞧,程序在发送请求后 挂起但是在最后一次 println
调用之前。
据我所知,HTTP 请求需要在 header 后提供一个空行,其中行分隔符必须是 \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());
至少,我可以通过这些更改确认程序在我的机器上也能正常工作。
关于java - 简单的java http客户端没有服务器响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9959573/