Pull to refresh

Comments 42

В данном случае даже близко не стоит задача написать полнофункциональный http-сервер)) Тут просто иллюстрация основ того, как устроен любой http-сервер и как происходит взаимодействие по протоколу HTTP.

Вот совсем не так устроен, даже не близко.
Для начала сделайте обработку запроса в отдельном треде: либо новом, либо из пула. Это добавит всего пару строк, но сделает ваш сервер многопользовательским. А то вы так бодро и оптимистично из сокета читаете, что как-будто кто-то обязан доставить вам незамедлительно весь http-запрос, а также моментально отправить ваш ответ. А вот треды исключат блокировку, и ваш сервер сразу станет актуальным на период до 2002 года.


В 2002 году вышла Java 1.4, в которой, наконец, запилили неблокирующий NIO, который предлагал совершенно другую модель взаимодействия. Треды стали ненужны, ну или не столь актуальны, но прогать стало на порядки сложнее. Поэтому Apache Mina или Netty.

Поверьте, я про это знаю) Но в данном случае такой задачи даже близко не стояло. Задача была написать короткий и простой код, которого достаточно чтобы принять HTTP запрос и ответить на него так, чтобы браузер понял. Это материал для совсем новичков, кто раньше никогда не писал веб приложений.

Так это ж для меня :)
Вот Java Core курс пойду и обязательно вернусь!

Но видимо текст не очень хорошо написан, если приходится в который раз это объяснять. Увы.

Как устроен сервер скрыто в ServerSocket

Пока что туда мы не пойдём)

Слишком простой пример, что бы называться «Простейшим HTTP-сервером на Java».

Если хотите показать, как работают сокеты, что сделайте чат на сокетах.

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

Ну это же неверно.

Вся суть HTTP — именно в спецификациях. Посмотрите, например, как лишь малую часть спецификации обсуждают в этой этой недавней теме REST страсти по 200.

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

Если хотите показать работу с сокетами, то сделайте простой чат.

Если ходите рассказать сетевую модель, то покажите это: ru.wikipedia.org/wiki/Сетевая_модель_OSI
Ох, чат. Я как раз на Java решил написать чат, с клиентом и сервером.
И работы сокетов там на несколько строк. Все остальное это огромная обертка, которую я никак не могу заставить себя продолжить писать.

Пример выше как раз отлично показывает работу сокетов «на один экран».
Пример выше как раз отлично показывает работу сокетов «на один экран».

Если хочется показать работу сокетов на примере HTTP, то нужно делать «простейший HTTP/1.0-клиент», а не сервер.

А преподавать что-то не зная сути вопроса я бы вообще не рискнул. Больше будет вреда, чем пользы.
Возможно, по этому то мы с вами и не преподаем :-)

Ну, тут то как раз логика понятна. Напишем крошечный сервер, а потом такой же клиент для него. Чтобы так сказать «полное покрытие было».
Полагаю, логика (ошибочная) была другая, а именно: что бы показать, что мы сделали полноценный HTTP-сервер продемонстируем, что можем к нему обратиться из браузера (популярный браузер — это авторитетная вещь) и получить ответ.

На самом деле, можно продемонстрировать работу клиента и «авторитетной вещи», например, обратившись к «google.com» по порту 80.

Или на «ya.ru» с запросом:

GET / HTTP/1.1
Host: ya.ru


И, включив отладку в браузере (Ctrl+Shift+I) и показав, что тоже самое видит и браузер.

И для этого совсем не обязательно даже писать программу, достаточно использовать telnet.

А упор при рассказе про HTTP нужно делать на понятия, стандарты, сценарии, демонстрации с помощью браузерного инструмента разработчика: developers.google.com/web/tools/chrome-devtools/network
Логика была примерно такой, как вы пишете. Чем она плоха я не очень понимаю. И уж точно данный пример не отменяет необходимости изучать понятия и стандарты HTTP, но после подобного примера это изучение будет основано на понимании того, что происходит на самом деле. HTTP перестанет быть «абстрактным конем в вакууме».
Я про HTML вообще не упоминал.

HTTP перестанет быть «абстрактным конем в вакууме».

По моему мнению, это введение в заблуждение.

Если вы сделаете «Простой HTTP/1.0-клиент», то претензий к вам, по сути, не будет.

Если вы заявляете, что сделали «Простой HTTP-сервер», то это опасное введение в заблуждение.
Про HTML была опечатка. Думаю, что понял, что не так. Подумаю, как исправить.

Собственно, в этом и была цель! А если сравнивать с чатом, то тут в качестве клиента выступает не какой-то ещё кусок кода, а такая всем хорошо известная вещь, как веб браузер.

По-моему вполне полезная статья. А если написать вторую часть, с примерами разбора и парсинга/фильтрации параметров, так совсем хорошо будет. Хоть джуны, которые кроме спринг-бута ничего больше и не видели, смогут посмотреть "как это сделано"

не стесняйтесь использовать com.sun.net.httpserver
А лучше сразу Spring Boot! Не об этом же статья)

Использовать можно что угодно. Только понимать нужно, как оно работает

Чего то как то не современно (если конечно заголовок статьи соответствует ее содержимому), вроде начиная с Oracle JDK 1.6 есть класс HttpServer:

Пример HTTP-сервера на com.sun.net.httpserver.HttpServer
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class App {
    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.createContext("/test", new MyHandler());
        //Thread control is given to executor service.
        server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
        server.start();
    }
    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            String response = "This is the response";
            long threadId = Thread.currentThread().getId();
            System.out.println("I am thread " + threadId );
            response = response + "Thread Id = "+threadId;
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }
}


Суть статьи не в том, чтобы написать HTTP сервер, а в том, чтобы показать что у всех подобных серверов внутри. Очень и очень многие используют HttpServer, сервлеты и тому подобное даже близко не представляя, как все это работает.

Продолжайте! На самом деле этой темы на 5 небольших статей легко хватит.
Мне понятно, что можно и не писать очередную статью, а отправить "гуглить" или смотреть исходники популярных библиотек…
Но тем и хорош хабр, что дает возможность на базе таких статей обсудить те или иные решения.

Есть мысль о цикле статей «Изучаем HTTP и пишем Web сервер». Надеюсь времени на это наскребу.
А таких статей на Хабре точно не было?
Как-то мудрый коллега сказал мне, что одна из главных проблем нашей профессии в том, что почти все программы (статьи) уже написаны. Но повод ли это прекращать старания?)
В научных статьях принято читать «коллег» и дополнять то, что не освещено или описано было не так хорошо, как в новой пердлагаемой статье. Ведь это только улучшит материал и даст возможность новым читателям прочитать и другие статьи на данную тему.

Например так старался делать Иван Головач в своих статьях: ivangolovach
Я наивно думал, что суть статьи соответствует заголовку)

Уже понял, что заголовок не удачен. Думаю над новым.

Стоит взять в привычку никогда не испольовать Reader/Writer обертки без явного указания кодировки:


// не надо так
new InputStreamReader(socket.getInputStream())
// надо так
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)

Такой подход спасет от большого количества боли.

Sign up to leave a comment.

Articles