Вопрос по http, sockets, java – Простой Http-сервер с Java / Socket?

23

В настоящее время я создаю небольшой HTTP-сервер, который возвращает статическую страницу<p>Hello!</p>... I tried with sockets with 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 (извините за французский язык ...)

Ваш Ответ

5   ответов
1

Вам нужны правильные разделители строк (\r\n) между каждой строкой вывода. Недостаточно просто объединить их - что вы можете увидеть, распечатав ответ.

Ему нужно \ r \ n. Это HTTP.
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 в строку.

= & GT; out.flush (); Marwen Trabelsi
Спасибо! У меня Windows7, я пробовал это, но все равно это не работает .... Marwen Trabelsi
0

Просто напоминание: этоnot HTTP-сервер, как следует из названия. Это сокет, который записывает один конкретный жестко закодированный HTTP-ответ (при условии, что он исправлен в соответствии с предложениями в других ответах). Даже если вы динамически изменили возвращаемый контент и длину заголовка контента, этого все равно недостаточно, чтобы соответствовать протоколу HTTP.

Как я научился трудному пути во время написанияJLHTTP, HTTP намного больше, чем это. Дело не в том, что это очень сложно, а в том, что существует множество дополнительных деталей и требований, которые должны быть надлежащим образом обработаны. Вы можете прочитать RFC (основной протокол определен в RFC 7230 или более раннем RFC 2616), чтобы узнать больше о том, что это влечет за собой.

Я также могу предложить исходный код JLHTTP в качестве справочного материала для хорошо документированной минимально совместимой реализации HTTP-сервера - это один файл, в настоящее время ~ 3 тыс. Строк, из которых почти половина - документация. Его цель - быть крошечным, но послушным. Я думаю, что просмотр кода может быть полезен всем, кто хочет узнать, что должен делать HTTP-сервер. Как я уже сказал - не очень сложно, но с множеством мелких деталей.

На самом деле, если быть точным, JLHTTP не настолько минимален, насколько это возможно - он включает в себя несколько полезных дополнительных функций, таких как обработка многочастных данных формы для загрузки файлов или поддержка HTTPS, которые не требуются самим протоколом HTTP. Но вы можете легко удалить эти части (или просто пропустить их) и получить действительно минимальную реализацию Java HTTP-сервера.

30

В дополнение к \ 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();
    }
}
Ваш заголовок запроса прочитан, хотя цикл неверен. Я добавлю рабочий пример к моему ответу.
Забудь мой комментарий.
Я пробовал это, но оно все еще не работает ... (см. Мое обновление). Marwen Trabelsi
Джоэл, ты забыл очистить выходной поток в своем примере. Если вы попробуете этот кусок кода с большим количеством HTML, он не будет работать правильно.
4

и причина, по которой ничего не видно в браузере, заключается в том, что вы неправильно рассчитали количество символов.

Это должно быть 57 вместо 59.

Еще лучше подсчитать количество символов автоматически, но я считаю, что ваш образец - это просто образец.

Ну что ж, это сработало для меня. Это должно быть на вершине :)

Похожие вопросы