28

我目前正在创建一个返回静态页面的小型 HTTP 服务器<p>Hello!</p>......我尝试使用带有 Java 的套接字:

  public static void main(String[] args) throws Exception {

        // création de la socket
        int port = 1989;
        ServerSocket serverSocket = new ServerSocket(port);
        System.err.println("Serveur lancé sur le port : " + port);

        // repeatedly wait for connections, and process
        while (true) {

            // on reste bloqué sur l'attente d'une demande client
            Socket clientSocket = serverSocket.accept();
            System.err.println("Nouveau client connecté");

            // on ouvre un flux de converation

           BufferedReader in = new BufferedReader(
                           new InputStreamReader(clientSocket.getInputStream())
                          ); 
            PrintWriter out = new PrintWriter(
                         new BufferedWriter(
                            new OutputStreamWriter(clientSocket.getOutputStream())), 
                         true);   

            // chaque fois qu'une donnée est lue sur le réseau on la renvoi sur le flux d'écriture.
            // la donnée lue est donc retournée exactement au même client.
            String s;
            while ((s = in.readLine()) != null) {
                System.out.println(s);


       out.write("HTTP/1.0 200 OK\r\n");
       out.write("Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n");
       out.write("Server: Apache/0.8.4\r\n");
       out.write("Content-Type: text/html\r\n");
       out.write("Content-Length: 59\r\n");
       out.write("Expires: Sat, 01 Jan 2000 00:59:59 GMT\r\n");
       out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n");
       out.write("\r\n");
       out.write("<TITLE>Exemple</TITLE>");
       out.write("<P>Ceci est une page d'exemple.</P>");
  }

            // on ferme les flux.
            System.err.println("Connexion avec le client terminée");
            out.close();
            in.close();
            clientSocket.close();
        }
    }

此代码不包含任何错误,我从浏览器收到如下响应:

GET / HTTP/1.1
Host: localhost:1989
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5 Comodo_Dragon/19.0.3.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

但我的问题是我在浏览器上没有页面?请问有什么帮助吗?

PS:我已经读过这篇文章:http ://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol ,(我很抱歉法语......)

4

5 回答 5

34

除了\r\n在每个请求标头行之后,您还必须在标头之后发送一个空行。例子:

out.write("HTTP/1.0 200 OK\r\n");
// Header...
out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n");
out.write("\r\n"); // The content starts afters this empty line
out.write("<TITLE>Hello!</TITLE>");
// Content...

我更正了您的代码以使其正常工作(但它仍然不完美,您应该在单独的线程中处理每个请求,例如使用java.util.concurrent.ThreadPoolExecutor):

public static void main(String[] args) throws Exception {
    // création de la socket
    int port = 1989;
    ServerSocket serverSocket = new ServerSocket(port);
    System.err.println("Serveur lancé sur le port : " + port);

    // repeatedly wait for connections, and process
    while (true) {
        // on reste bloqué sur l'attente d'une demande client
        Socket clientSocket = serverSocket.accept();
        System.err.println("Nouveau client connecté");

        // on ouvre un flux de converation

        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));

        // chaque fois qu'une donnée est lue sur le réseau on la renvoi sur
        // le flux d'écriture.
        // la donnée lue est donc retournée exactement au même client.
        String s;
        while ((s = in.readLine()) != null) {
            System.out.println(s);
            if (s.isEmpty()) {
                break;
            }
        }

        out.write("HTTP/1.0 200 OK\r\n");
        out.write("Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n");
        out.write("Server: Apache/0.8.4\r\n");
        out.write("Content-Type: text/html\r\n");
        out.write("Content-Length: 59\r\n");
        out.write("Expires: Sat, 01 Jan 2000 00:59:59 GMT\r\n");
        out.write("Last-modified: Fri, 09 Aug 1996 14:21:40 GMT\r\n");
        out.write("\r\n");
        out.write("<TITLE>Exemple</TITLE>");
        out.write("<P>Ceci est une page d'exemple.</P>");

        // on ferme les flux.
        System.err.println("Connexion avec le client terminée");
        out.close();
        in.close();
        clientSocket.close();
    }
}
于 2012-05-28T17:13:04.173 回答
5

这只是您最后一个问题的答案,浏览器中看不到任何内容的原因是您计算的字符数不正确。

它应该是 57 而不是 59。

更好的是自动计算字符数,但我相信您的样本只是一个样本。

于 2013-04-03T14:16:06.377 回答
1

你用的是什么机器?什么操作系统?如果您运行的是 UNIX 机器,那么 println 将不起作用,因为它只发送一个 LF 字符。HTTP 需要 CR 和 LF 作为其标头。尝试将 \r 添加到字符串的末尾,看看是否有效。

哦,还有,你的:

  out.println("HTTP/1.0 200 OK"+
"Date: Fri, 31 Dec 1999 23:59:59 GMT"+
"Server: Apache/0.8.4"+
"Content-Type: text/html"+
"Content-Length: 59"+
"Expires: Sat, 01 Jan 2000 00:59:59 GMT"+
"Last-modified: Fri, 09 Aug 1996 14:21:40 GMT"+

它正在打印一个长字符串。

将它们更改为每个字符串的 println,或将 \r\n 添加到字符串中。

于 2012-05-28T17:03:13.567 回答
1

\r\n您需要在每行输出之间使用正确的行分隔符 ( )。仅仅连接它们是不够的 - 如果您打印出响应,您可以看到它。

于 2012-05-28T17:03:57.057 回答
1

只是提醒一下:这不是一个 HTTP 服务器,正如标题所暗示的那样。它是一个套接字,它写出一个特定的硬编码 HTTP 响应(假设它是根据其他答案中的建议修复的)。即使您动态更改了返回的内容和内容长度标头,这仍然不足以符合 HTTP 协议。

正如我在编写JLHTTP时所学的那样,HTTP 远不止这些。不是很复杂,只是有很多额外的细节和要求需要妥善处理。您可以阅读 RFC(核心协议在 RFC 7230 或较旧的 RFC 2616 中定义)以了解有关这需要的更多信息。

我还可以提供 JLHTTP 源代码作为 HTTP 服务器的一个有据可查的最小兼容实现的参考 - 它是一个文件,目前约 3K 行,其中几乎一半是文档。它的目标是小而顺从。我认为查看代码对于任何想要了解 HTTP 服务器必须做什么的人都是有用的。正如我所说 - 不是很复杂,但有很多小细节。

实际上,准确地说,JLHTTP 并没有尽可能小——它确实包含一些有用的额外功能,例如处理文件上传的多部分表单数据或支持 HTTPS,这些不是 HTTP 协议本身所要求的。但是您可以轻松地将这些部分去掉(或跳过它们)并实现真正最小的 Java HTTP 服务器实现。

于 2018-06-07T08:33:49.003 回答