这是我的主类 - 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 block ,该 block 包含:
while((t = in.readLine()) != null)
将执行,并成功显示服务器的响应。但是,显示响应后,循环将停止执行,代码不会前进到finally block 。该程序似乎在 while 循环之后没有继续。有人知道为什么吗?
即, System.out.println("完成"); 永远不会到达,不会引发异常或编译器错误。
最佳答案
服务器保持连接打开以允许客户端发送进一步的请求。客户端不应通过检测流已关闭来确定当前响应的结束,而是通过响应中发送的“Content-Length” header 来确定。
以下是如何重写循环以允许它提取该长度值:
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());
}
关于java - Try/catch block 带有 while 语句,用于处理套接字数据,不会继续。没有明显的错误(我认为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17776828/