0

这是我的主要课程 - Main.java。用于控制请求者,但为了完整性而添加。

import java.io.IOException;

import HtmlRequester.Requester;

public class Main {

public static void main(String[] args) {
    Requester rq = new Requester("www.google.co.za", 80);

    try {
        rq.htmlRequest();
    } catch (IOException e) {
        e.printStackTrace();
        System.err.println("Connection failed.");
        System.exit(-1);
    }

}
}

这是 requester.java,为简短而编辑。

package HtmlRequester;
import java.net.*;
import java.io.*;

public class Requester{
    Socket httpSocket = null;
    PrintWriter out = null;
    BufferedReader in = null;
    String server;
    int port;

public void setAttributes(String server, int port){
    this.server = server;
    this.port = port;
}

public String htmlRequest(String server, int port) throws IOException{
    try {
        httpSocket = new Socket(InetAddress.getByName(server), port);
        out = new PrintWriter(httpSocket.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(
                httpSocket.getInputStream()));
    } catch (UnknownHostException e) {
        System.err.println("Don't know about host: " + server);
        System.exit(-1);
    } catch (IOException e) {
        System.err.println("Couldn't get I/O for "
                           + "the connection to: " + server + "on port " + port);
        System.exit(-1);
    }
    finally{
        System.out.println("Successful connection.");
    }

    out.println(compileRequestText());
    out.println("");

    String t;
    String ret = "";
    System.out.println("wait...");
    try {
        while((t = in.readLine()) != null)
        {
        ret.concat(t);
        System.out.println(t);
        }

        System.out.println("done");
    }
    catch(SocketException e)
    {
        System.err.println("Socket Exception :(");
    }
    System.out.println("Succesful data transfer.");

    out.close();
    in.close();
    httpSocket.close();
    return ret;
}

private String compileRequestText(){
    String ret = "GET / HTTP/1.1";

    return ret;
}
}

发生的情况是 Request.java 中的第二个 try-catch 块,该块包含:

while((t = in.readLine()) != null)

将执行,并成功显示来自服务器的响应。但是,在显示响应后,循环将停止执行,代码不会前进到 finally 块。在那个while循环之后程序似乎没有继续。有人知道为什么吗?

即 System.out.println("done"); 永远不会到达,不会抛出异常或编译器错误。

4

2 回答 2

1

服务器保持连接打开以允许客户端发送进一步的请求。客户端不应通过检测流已关闭,而是通过响应中发送的“Content-Length”标头来确定当前响应的结束。

以下是如何重写循环以允许它提取该长度值:

  InputStream in = httpSocket.getInputStream();
  StringBuilder sb = new StringBuilder();
  boolean content = false;
  for (int i = 0; true; ++i) {
    if (content && i >= len)
      break;

    int ch = in.read();
    if(ch < 0)
      break;

    sb.append((char) ch);
    if (ch == '\n') {
      String s = sb.toString();
      if (!content && s.trim().isEmpty()) {
        content = true;
        i = 0;
      }
      if (len < 0)
        len = extractLength(s);

      System.out.print(s);
      sb = new StringBuilder();
    }
  }

  System.out.println(sb.toString());
  System.out.println("done");

这依赖于这两个辅助定义:

private static final String HEADER = "Content-Length: ";

private int extractLength(String s) {
  if (!s.startsWith(HEADER))
    return -1;
  return Integer.parseInt(s.substring(HEADER.length()).trim());
}
于 2013-07-21T21:37:54.917 回答
0

您的请求不完整:您应该添加Connection: close标头以及Host标头。参见例如http://www.jmarshall.com/easy/http/#http1.1clients

发生的事情是服务器使连接保持打开状态,因此您可以通过它发送更多请求,并且循环继续尝试读取结果。此标头通过要求服务器关闭连接来禁用该行为。

在发送请求后关闭到服务器的输出流也可能有效。

于 2013-07-21T21:05:26.167 回答