我的套接字客户端似乎只接收来自HTTP服务器的第一个响应。为什么?

时间:2012-03-03 23:38:02

标签: java sockets network-programming

我正在尝试开发一个允许我在线程上运行套接字的类,并且它随时允许我通过它发送数据,以及在数据到达时接收通知。它应该假设没有诸如仅在首先发送消息之后接收消息等的事情,等等。 由于某种原因,以下代码仅打印第一个请求的响应:

public static void main(String[] args) throws IOException {
    TCPClient client = new TCPClient(new TCPClientObserver());
    client.connect("www.microsoft.com", 80);

    sleep(1000);
    client.send("HTTP GET");

    sleep(5000);
    client.send("XYZ");
}

印刷

echo: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
echo: <HTML><HEAD><TITLE>Bad Request</TITLE>
echo: <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
echo: <BODY><h2>Bad Request - Invalid URL</h2>
echo: <hr><p>HTTP Error 400. The request URL is invalid.</p>
echo: </BODY></HTML>

这是套接字的核心逻辑:

        echoSocket = new Socket("www.microsoft.com", 80);
        out = new PrintWriter(echoSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(
                echoSocket.getInputStream()));

        while (true) {
            String response = in.readLine();
            if (response != null)
                System.out.println("echo: " + response);
        }

我猜问题出在我的循环中?

我的应用程序的完整测试代码可以在这里看到: http://codepad.org/bmHwct35

由于

4 个答案:

答案 0 :(得分:2)

问题不在于循环,而是您发送的第一个请求。 “HTTP GET”是无效请求,服务器应响应“400 Bad request”,然后关闭连接。这就是为什么你没有得到第二条消息的回应。尝试有效的HTTP请求,例如“GET / HTTP / 1.1 \ r \ nHost:www.microsoft.com \ r \ n \ r \ n”而不是。默认情况下,HTTP 1.1连接保持活动状态,因此您可以发送多个连接并接收后续响应。

答案 1 :(得分:1)

问题是HTTP服务器与HTTP协议通信,而您的客户端代码没有正确地协商协议。相反,它打开一个普通的套接字并编写似乎基于猜测的随机内容。

HTTP协议在this document中指定。如果你阅读它,你会发现你正在做的事情与客户应该做的事情完全不同。

我建议您不要尝试以这种方式实现客户端。从头开始实现HTTP协议的客户端工作太多了......世界上还不需要另一个flakey HTTP客户端。使用标准URL / HttpURLConnection API,或使用第三方HTTP客户端库。


在您的情况下,400响应很可能是发送格式错误的请求的结果。 HTTP GET请求(实际上是任何HTTP请求)应该包含第一行中的目标URL。阅读规范。

答案 2 :(得分:1)

您发送的第一个请求是无效的,在回复后服务器将关闭连接。在您的代码中,您将被卡在while (true)循环中,因为当连接/流关闭(到达流末尾)时,您将从null返回readLine

while (true) { // <-- never terminates
  String response = in.readLine();
  if (response != null) // <- now null all the time
    System.out.println("echo: " + response);
}

答案 3 :(得分:1)

假设HTTP 400是您所期望的,如果readLine()返回null,则需要中断循环。这通常是这样写的:

while ((line = in.readLine()) != null)
{
    // ...
}