0

我正在尝试为 Java 构建我自己的嵌入式 HTTP 服务器,用于内部封闭系统的非常具体的用途。使用已经存在的嵌入式解决方案意味着我需要将它们剥离以针对我内部系统的特定用例进行改装。

我已经设法让我的 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 正文。我可以知道解决上述问题的一些解决方案吗?

谢谢。

4

2 回答 2

3

HTTP 标头和正文由行分隔(另请参阅 HTTP RFC,尤其是“5 请求”一章)。您的服务器读取套接字Inputstream但在空行上中断:

if (line.trim().isEmpty()) {
   break;
}

因此很明显你不会接受身体。你应该完全消耗掉Inputstream

除此之外,我建议您使用现有的解决方案。有大量的 HTTP 服务器实现,它们在现实世界的使用中经过了很好的测试和证明。使用现有的轻量级服务器(例如 Jetty、Netty 或类似服务器)为您省去很多麻烦。

于 2013-08-02T10:11:12.607 回答
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 。

于 2013-08-05T05:29:49.607 回答