我正在尝试使用HTTP 1.1功能实现基本的Web服务器。服务器的超时时间为2秒 - 如果2秒内没有请求新数据包,则套接字将关闭。
private void start(int port) throws IOException{
System.out.println("Starting server on port " + port);
ServerSocket serverSocket = new ServerSocket(port);
try{
while(true){
Socket clientSocket = serverSocket.accept();
handleClientSocket(clientSocket, serverSocket);
}
}catch(SocketTimeoutException e){
System.out.println("Time's up");
}
}
/**
* Handles requests sent by a client
* @param client Socket that handles the client connection
*/
private void handleClientSocket(Socket client, ServerSocket server) throws IOException, SocketTimeoutException {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line;
while((line = in.readLine()) != null && !line.isEmpty()){
String[] header = line.split(" ");
if(header[0].equals("GET")){
switch(header[2]){
case "HTTP/1.0":
generate(client, in.readLine(), header);
System.out.println("close");
client.close();
break;
case "HTTP/1.1":
generate(client, in.readLine(), header);
client.setSoTimeout(2000);
break;
default:
System.out.println("This is not suppose to happen.");
break;
}
}
}
}
程序以下列格式读取缓冲的数据包输入:
GET \background.png HTML\1.1
Host: localhost:8000
重复读取此输入,直到缓冲输入为空。
因为setSoTimeout
嵌套在while循环中,所处理的每个新数据包都会将计时器重置为2000ms。
封装此方法的方法handleClientSocket
会抛出SocketTimeoutException
,它会被start
方法中的try-catch块捕获。
因此,当达到超时时,它应该打印Time's up
。
我可以连接到网络服务器并获得一个工作页面,但是,在发送请求后约2秒我无法模拟“连接已关闭”。
答案 0 :(得分:1)
while(!(line = in.readLine()).isEmpty()){
无效。您必须首先测试它为null:
while((line = in.readLine()) != null && !line.isEmpty()){
程序以下列格式读取缓冲的数据包输入:
GET \background.png HTML\1.1
不,它没有。它查找HTTP/1.1
,反斜杠应该是HTTP中的正斜杠,所以应该是:
GET /background.png HTTP/1.1
那是你正在测试的内容。
请注意,HTTP中的行分隔符定义为\r\n
,而不只是\n
。
重复读取此输入,直到缓冲输入为空。
不,不是。读取空白行,对等体关闭连接或发生读取超时。当缓冲的输入为空时,readLine()
不会返回null或空行'。它会阻止。
因为setSoTimeout嵌套在while循环中,所处理的每个新数据包都会将计时器重置为2000ms。
不必要的。设置后,超时保持不变。你不需要每次循环都设置它。您应该在循环之前将其设置为。目前,第一次读取时根本没有读取超时。
您也丢弃每个奇数行。这看起来不对。
如果您未从此代码中获取SocketTimeoutExceptions
,则每次致电readLine()
时,数据都会在超时期限内到达。
否则当你没有读取超时时,你会在第一个readLine()
中阻止。
或者你因为第一次错误而得到NullPointerExceptions
。
编辑或者你根本不在readLine()
。你不是。您已处理了一个完整的请求,将其读取到标题的末尾,然后返回到main方法。所以,没有读取超时。我设法通过重构你的接受循环来获得SocketTimeoutException
,如下所示:
while (true)
{
try (Socket clientSocket = serverSocket.accept())
{
System.out.println("accepted " + clientSocket);
for (;;)
{
handleClientSocket(clientSocket, serverSocket);
}
}
catch (SocketTimeoutException e)
{
System.out.println("Time's up");
}
System.out.println("request handling ended");
}