在本地服务器上解析来自浏览器的 HTTP 请求:Java
我正在尝试创建一个简单的 HTML 服务器,它将从浏览器读取请求,从请求中解析所请求的文件,然后将适当的 HTML 返回给浏览器。我需要能够处理多个请求,因此我当前有一个 Server 类作为另一个可运行类 RequestHandler 的父级。每次在服务器上建立连接时,都会运行可运行类 RequestHandler 的一个新实例。
package server;
import java.io.IOException;
import java.net.ServerSocket;
public class Server {
public static void main(String[] args){
try{
ServerSocket serverSocket = new ServerSocket(8000);
for(;;){
Object block = new Object();
RequestHandler handler = new RequestHandler(block, serverSocket);
handler.start();
try{
synchronized(block){
System.out.println("Server thread paused...");
block.wait();
System.out.println("Server thread creating new RequestHandler...");
}
}catch(InterruptedException e){
System.out.println("Can't be interrupted!");
e.printStackTrace();
}
}
}catch(IOException e){
System.out.println("IOException!");
e.printStackTrace();
}
}
}
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class RequestHandler extends Thread {
Object block;
ServerSocket serverSocket;
BufferedReader socketReader;
PrintWriter socketWriter;
public RequestHandler(Object block, ServerSocket serverSocket){
this.block = block;
this.serverSocket = serverSocket;
}
@Override
public void run() {
try{
System.out.println("Waiting for request...");
Socket clientSocket = serverSocket.accept();
System.out.println("Connection made.");
synchronized(block){
System.out.print("Notifying server thread...");
block.notify();
System.out.println("...done");
}
socketReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
socketWriter = new PrintWriter(clientSocket.getOutputStream(), true);
String input;
while((input = socketReader.readLine()) != null){
System.out.println(input);
}
}catch(IOException e){
System.out.println("IOException!");
e.printStackTrace();
}
}
}
我遇到的问题是,我不确定如何组合请求的所有行,以便我可以解析请求的文件。如果它只是不断地等待请求输入,我将永远无法解析整个请求。我该如何解决这个问题?
I'm trying to make a simple HTML server that will read a request from my browser, parse the requested file from the request, then serve the appropriate HTML back to the browser. I need to be able to handle multiple requests, so I currently have a Server class acting as a parent of another runnable class RequestHandler. Each time a connection is made on the server, a new instance of the runnable class RequestHandler is run.
package server;
import java.io.IOException;
import java.net.ServerSocket;
public class Server {
public static void main(String[] args){
try{
ServerSocket serverSocket = new ServerSocket(8000);
for(;;){
Object block = new Object();
RequestHandler handler = new RequestHandler(block, serverSocket);
handler.start();
try{
synchronized(block){
System.out.println("Server thread paused...");
block.wait();
System.out.println("Server thread creating new RequestHandler...");
}
}catch(InterruptedException e){
System.out.println("Can't be interrupted!");
e.printStackTrace();
}
}
}catch(IOException e){
System.out.println("IOException!");
e.printStackTrace();
}
}
}
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class RequestHandler extends Thread {
Object block;
ServerSocket serverSocket;
BufferedReader socketReader;
PrintWriter socketWriter;
public RequestHandler(Object block, ServerSocket serverSocket){
this.block = block;
this.serverSocket = serverSocket;
}
@Override
public void run() {
try{
System.out.println("Waiting for request...");
Socket clientSocket = serverSocket.accept();
System.out.println("Connection made.");
synchronized(block){
System.out.print("Notifying server thread...");
block.notify();
System.out.println("...done");
}
socketReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
socketWriter = new PrintWriter(clientSocket.getOutputStream(), true);
String input;
while((input = socketReader.readLine()) != null){
System.out.println(input);
}
}catch(IOException e){
System.out.println("IOException!");
e.printStackTrace();
}
}
}
The problem I'm running into is that I'm not sure how to combine all the lines of the request so that I can parse the requested file. If it's just constantly waiting on request input, I'll never get to a point where I can parse the entirety of the request. How can I solve this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只有当客户端和服务器之间的连接关闭时,您的 while 循环才会中断。由于客户端在发送请求后正在同一连接上等待响应,因此连接将保持打开状态,因此 readline() 将阻塞。在 while 循环中,您必须在每一行之后检查是否已到达请求数据的末尾。对于 GET 请求,您必须查找 HTTP 标头后面的空行。对于 POST 请求,您必须解析传入标头以查找。然后处理剩余的标头,查找空行(就像 GET 情况一样)。一旦你找到了空白,你必须阅读字节。此时,您知道您已经完成了请求数据的处理,并且应该跳出读取循环。
阅读 HTTP 规范了解详细信息。
your while loop will only break once the connection between the client and the server is closed. Since the client is waiting on the same connection for a response after sending the request the connection will remain open, so your readline() will block. In your while loop you have to check after every line whether you have reached the end of the request data. For GET requests, you have to look for a blank line following HTTP headers. For POST requests, you have to parse incoming headers looking for <Content-Length: N>. THen process the remaining headers looking for the blank line (just like in the GET case). Once you find the blank like, you have to read <N> bytes. At this point you know you've finished processing request data and should break out of the read loop.
Read the HTTP spec for details.
第一行给出请求方法以及请求的路径,接下来的行是请求标头,标头块以空行结尾。
也就是说,您正在重新发明轮子:您可以使用 com.sun.net.httpserver.HttpServer
The first line gives you the request method as well as the requested path, the following lines are the request headers, the header block ends with a blank line.
That said, you are reinventing the wheel: you could use com.sun.net.httpserver.HttpServer