Курс по Raku / Функционално, паралелно, реактивно и уеб програмиране / Уеб програмиране / Прост HTTP сървър

Обслужване на много заявки

Сървърът от предишната страница обработи една заявка и спря. Истинският сървър продължава да работи, отговаряйки на клиент след клиент. Обвийте стъпките „приеми—прочети—отговори“ в loop — и понеже цикълът споделя променливите, декларирани около него, можете да пазите състояние между заявките. Тук сървърът брои клиентите си и казва на всеки неговия номер:

my $listener = IO::Socket::INET.new(
    :listen,
    :localhost('127.0.0.1'),
    :localport(8080),
);

my $customer = 0;

loop {
    my $conn = $listener.accept;
    $conn.recv;
    $customer++;

    # heredoc чрез qq:to дава спретнат шаблон — променливата се интерполира направо вътре
    my $body = qq:to/END/;
        Hello!
        You are customer number $customer.
        Thanks for visiting.
        END

    # първо изпращаме заглавката, после тялото — с два отделни записа
    $conn.print("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n");
    $conn.print($body);

    $conn.close;
}

.accept блокира, докато не се свърже клиент, а после връща нов сокет за точно този разговор. Понеже $customer живее извън цикъла, тя оцелява от една заявка към следващата: първият посетител е клиент 1, вторият — 2, и така нататък. Цикълът никога не свършва сам, така че сървърът работи, докато не го спрете с Ctrl-C.

Две подробности заслужават внимание:

  • Отговорът е записан на две части. Първият .print изпраща HTTP заглавката — реда за състояние, типа на съдържанието и празния ред, който завършва заглавките. Вторият изпраща тялото. На HTTP му е все едно дали те пристигат с един запис, или с няколко, така че разделянето държи непроменливата протоколна обвивка настрани от онази част, която наистина се променя.

  • Тялото идва от шаблон. qq:to/END/ е heredoc: низ qq, който продължава до реда END. Той обхваща няколко реда и интерполира $customer точно както всеки низ в двойни кавички, което го прави спретнато малко средство за шаблонизиране при изграждането на отговор. (Това е една от конструкциите за цитиране от по-рано в курса.)

Свържете се няколко пъти, за да видите как броячът се катери:

$ curl http://127.0.0.1:8080/
Hello!
You are customer number 1.
Thanks for visiting.
$ curl http://127.0.0.1:8080/
Hello!
You are customer number 2.
Thanks for visiting.

Такава обработка на заявките една след друга е най-простият вид сървър. Промишленият сървър би обслужвал и всяка връзка в собствена нишка или обещание, за да не може бавен клиент да задържа останалите — но сърцето му е точно този цикъл: приеми, прочети, отговори, повтори.

Навигация в курса

Отговор на заявка   |   Пътят с главни букви


💪 Или преминете направо към упражнението към този раздел.