Подтвердить что ты не робот

Простой сервер Http с Java/Socket?

В настоящее время я создаю небольшой 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, (извините за французский язык...)

4b9b3361

Ответ 1

В дополнение к \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();
    }
}

Ответ 2

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

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

Лучше еще иметь число символов, рассчитанных автоматически, но я считаю, что ваш образец является просто образцом.

Ответ 3

Какую машину вы используете? Какая ОС? Если вы используете 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 в строку.

Ответ 4

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

Ответ 5

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

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

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

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