我正在尝试使用套接字模拟简单的HTTP服务器和客户端。 BufferedReader用于逐行读取请求。 为了识别套接字输入流的结束,使用BufferedReader的ready()方法。
Java Doc for ready:
Returns:
True if the next read() is guaranteed not to block for
input, false otherwise. Note that returning false does not
guarantee that the next read will block.
当我从浏览器访问服务器时,此工作正常。但是当我从java应用程序中尝试它时,继续返回true。我是否需要在Java程序中包含任何内容,以便BufferedReader准备好返回false?
服务器:
package com.test.http.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpWebServer {
private static final String ROOT_URL = "/";
private static final String FAV_ICON_URL = "/favicon.ico";
private static final String GET_METHOD = "GET";
private static final String POST_METHOD = "POST";
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8081);
System.out.println("Established connection........."
+ serverSocket.getLocalSocketAddress());
Socket clientSocket = null;
while (true) {
clientSocket = serverSocket.accept();
new HttpWebServer().handleRequest(clientSocket);
}
}
private void handleRequest(Socket clientSocket) throws IOException {
System.out.println("Received a http request with data as follows");
InputStream socketInputStream = clientSocket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(
socketInputStream));
String line = null;
String url = null;
String method = null;
StringBuilder isStringBuilder = new StringBuilder();
while ((line = br.readLine()) != null) {
isStringBuilder.append(line).append("\r\n");
if (url == null && !line.isEmpty()) {
method = line.split("\\ ")[0];
url = line.split("\\ ")[1];
}
if (!br.ready())
break;
}
System.out.println(isStringBuilder.toString());
if (url != null && (method != null) && method.trim().equals(GET_METHOD)) {
if (url.trim().equals(ROOT_URL))
handleGetRootRequest(clientSocket);
else if (url.trim().equalsIgnoreCase(FAV_ICON_URL))
handleGetIconRequest(clientSocket);
}
/*
* byte[] bytes = new byte[1024];
*
* int count = 0;
*
* do{ count = socketInputStream.read(bytes); String output = new
* String(bytes, 0, count); System.out.print(output);
* System.out.flush();
*
* //count = socketInputStream.read(bytes); System.out.println(count);
*
* }while(socketInputStream.available() > 0);
*/
System.out.println("Completed processing request");
}
private void handleGetIconRequest(Socket clientSocket) {
System.out.println("Yet to implement !!");
}
private void handleGetRootRequest(Socket clientSocket) throws IOException {
OutputStream clientOS = clientSocket.getOutputStream();
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK ").append("\r\n").append("\r\n")
.append("<TITLE>").append("SUCCESS").append("</TITLE>");
String response = sb.toString();
clientOS.write(response.getBytes("UTF-8"));
clientOS.flush();
clientOS.close();
clientSocket.close();
}
}
客户端:
package com.test.http.client;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class HttpSimpleClient {
public static void main(String[] args) throws UnknownHostException, IOException{
Socket socket = new Socket("localhost",8081);
StringBuilder requestBuilder = new StringBuilder();
requestBuilder.append("GET")
.append(" / ").append("HTTP/1.1").append("\r\n")
.append("Connection: keep-alive").append("\r\n").append("\r\n")
.append(" Some Body");
OutputStream socketOutputStream = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socketOutputStream));
bw.write(requestBuilder.toString());
bw.flush();
System.out.println("<Client> Send:"+ requestBuilder.toString());
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
StringBuilder responseBuilder = new StringBuilder();
String line = null;
while((line = br.readLine()) != null){
responseBuilder.append(line);
if(!br.ready()){
break;
}
}
System.out.println(" Response: "+requestBuilder.toString());
socket.close();
}
}
在bw.flush();
关闭Socket本身之后关闭bw,同时读取输入流时出错。
答案 0 :(得分:2)
您应该阅读请求标题的末尾。那是"\r\n\r\n"
序列。
while ((line = br.readLine()) != null) {
isStringBuilder.append(line).append("\r\n");
if (url == null && !line.isEmpty()) {
method = line.split("\\ ")[0];
url = line.split("\\ ")[1];
}
if (line.isEmpty())
break;
}
如果您想阅读请求正文Some body
。您必须将Content-Length: LENGTH_OF_BODY
添加到请求标头中。服务器解析它,然后阅读LENGTH_OF_BODY
字节。在这种情况下,您无法使用BufferedReader
。