我正在尝试为内部封闭系统构建我自己的嵌入式HTTP Server for Java。使用已经存在的嵌入式解决方案意味着我需要剥离它们以针对我的内部系统的特定用例重新调整它们。
我设法让我的Java HTTPD从Web浏览器接收HTTP请求,但HTTPD收到的请求不完整。
下面是服务器线程代码(假装ServerSocket工作正常):
public class HttpThread implements Runnable {
private Socket socket;
private DataInputStream in;
private PrintStream out;
private BufferedReader br;
private String EOF = "\n";
private String STATUS_200 = "HTTP/1.1 200 OK" + EOF;
public HttpThread(Socket socket) throws IOException {
this.socket = socket;
this.in = new DataInputStream(this.socket.getInputStream());
this.out = new PrintStream(new BufferedOutputStream(this.socket.getOutputStream()));
}
@Override
public void run() {
System.out.println("New thread...");
try {
processInput();
//socket.close();
} catch (IOException ex) {
Logger.getLogger(HttpThread.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//System.out.println("Thread END...");
}
private String processInput() throws IOException {
String line;
StringBuilder buff = new StringBuilder();
br = new BufferedReader(new InputStreamReader(in));
while ((line = br.readLine()) != null) {
buff.append(line);
System.out.println(">>> " + line);
if (line.trim().isEmpty()) {
break;
}
}
out.print(STATUS_200);
out.print("Server: Test Server\n" +
"Content-Type: text/html; charset=UTF-8\n" +
"Connection: close");
out.print(EOF);
out.print("<html><body>yello</body></html>");
out.print(EOF);
out.flush();
System.out.println(STATUS_200);
return buff.toString();
}
}
我正在使用此HTML脚本来测试服务器线程以模拟POST请求:
<html>
<body onLoad="document.test.submit();">
<form action="http://localhost:9999/" method="POST" name="test">
<input type=hidden name="userid" value="1443"/>
<input type=hidden name="password" value="1443"/>
</form>
</body>
</html>
当我使用浏览器调用HTML代码时,Java HTTPD会收到不完整的响应:
New thread...
>>> POST / HTTP/1.1
>>> Host: localhost:9999
>>> Connection: keep-alive
>>> Content-Length: 25
>>> Cache-Control: max-age=0
>>> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
>>> Origin: null
>>> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36
>>> Content-Type: application/x-www-form-urlencoded
>>> Accept-Encoding: gzip,deflate,sdch
>>> Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
>>>
HTTP/1.1 200 OK
New thread...
>>> GET /favicon.ico HTTP/1.1
>>> Host: localhost:9999
>>> Connection: keep-alive
>>> Accept: */*
>>> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36
>>> Accept-Encoding: gzip,deflate,sdch
>>> Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
>>>
HTTP/1.1 200 OK
似乎HTTPD只接收了HTTP标头并停止接收POST主体。 我可以知道解决上述问题的一些解决方案吗?
感谢。
答案 0 :(得分:3)
HTTP标头和正文由空行(also see the HTTP RFC分隔,尤其是“5请求”一章。您的服务器读取套接字Inputstream
但在空行中断:
if (line.trim().isEmpty()) {
break;
}
因此显然你不会收到尸体。您应该完全使用Inputstream
。
除此之外,我建议您使用现有的解决方案。有大量的HTTP服务器实现,经过充分测试并在实际使用中得到验证。保存自己很多头痛并使用现有的轻量级服务器,例如Jetty,Netty或类似的。
答案 1 :(得分:0)
我使用以下代码切换了执行readline()的while循环:
int i;
byte[] buffer = new byte[2048];
i = in.read(buffer);
for (int j = 0; j < i; j++) {
buff.append((char) buffer[j]);
}
System.out.println(buff.toString());
问题解决了。
Pyranja,谢谢你的帮助。感谢http://kcd.sytes.net/articles/simple_web_server.php如果你简明扼要。不知怎的,br.readline()没有在空行之后正确读取行。
代码片段现在应该如下所示:
private String processInput() throws IOException {
String line;
StringBuilder buff = new StringBuilder();
int i;
byte[] buffer = new byte[2048];
i = in.read(buffer);
for (int j = 0; j < i; j++) {
buff.append((char) buffer[j]);
}
System.out.println(buff.toString());
out.print(STATUS_200);
out.print("Server: Test Server\n" +
"Content-Type: text/html; charset=UTF-8\n" +
"Connection: close");
out.print(EOF);
out.print("<html><body>yello</body></html>");
out.print(EOF);
out.flush();
System.out.println(STATUS_200);
return buff.toString();
}
我想学习如何构建一个简单的HTTP服务器是一个很好的经验:D。