eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programmingEmbedded HTTP Server › Re: Embedded HTTP Server
  • Data: 2020-06-08 21:20:38
    Temat: Re: Embedded HTTP Server
    Od: Maciej Sobczak <s...@g...com> szukaj wiadomości tego autora
    [ pokaż wszystkie nagłówki ]

    > Żeby Twojego rozwiązania użyć w jakimś normalnym programie, trzeba stworzyć wątek.

    Cała jedna linijka kodu. Której w prostych programach nawet nie trzeba (patrz
    przykłady).

    > Wygodne użycie, to byłoby coś takiego:
    >
    > int main() {
    > auto server = std::make_unique<http::Server>(8008, ".");
    >
    > server->start();

    Czyli też jedna dodatkowa linijka kodu, w dodatku zawsze, nawet w najprostszym
    programie.
    Więc na czym polega postęp?

    > // tu się dzieje magia, która programista uprawia
    > // a gdy się kończy scope, to server się sam zamyka
    > }

    Się tak łatwo nie zamyka, jeśli ma callbacki.

    > > Natomiast, nic nie stoi na przeszkodzie, żeby sobie zawołać funkcję
    server_start() 5 razy z różnymi portami, z 5 różnych wątków, bo ta funkcja i tak nie
    ma stanu globalnego. Nie trzeba mieć do tego klasy.
    >
    > Stoi, bo masz współdzieloną mapę routingu.

    Przyłapałeś mnie. Skupiłem się na portach - faktycznie mapa jest wspólna.
    Czyli twierdzisz, że ktoś będzie koniecznie chciał zrobić w jednym programie 5
    serwerów na różnych portach, ale tak, żeby takie same linki robiły w nich różne
    rzeczy?
    To brzmi jak ostra perwersja. Tylko dlaczego ja mam w tym uczestniczyć?

    Jeśli moja biblioteka miałaby swoją ułomnością powstrzymać kogoś przed tą perwersją,
    to nawet uznałbym to za moralny sukces. :-)

    > A, że masz ją współdzieloną, to też masz radosnego mutexa w głównej pętli.

    I w czym ten mutex przeszkadza, skoro go nawet nie widać?

    > No i to jest defekt. Ja chcę, żeby mój program się zamykał w cywilizowany sposób.
    > Callbacki są wołane w wątkach, robisz sobie na nie barierę (czyli np. latch) po
    zakończeniu głównej pętli i po kłopocie.

    O ile wszystkie wrócą. Zobacz przykład 6. Można go przepisać tak, że to funkcja
    get_updates() będzie robić to, co activity(). Czyli nigdy nie wróci.

    Ale owszem, jest to możliwe rozwiązanie, tylko wymaga zmiany koncepcji komunikacji.
    Teraz, w prostej implementacji, jest to komunikacja blokująca. Wątek obsługujący
    połączenie nie wróci, jeśli utknął na odczycie z gniazda (a w tym stanie spędza
    większość czasu), dopóki *klient* tego połączenia nie zamknie. Nie wystarczy sobie
    ustawić flagę.
    Można to rozwiązać wprowadzając dodatkowe mechanizmy typu select() albo poll(), ale
    zrobienie tego dobrze to złożoność porównywalna z całą resztą kodu i to są właśnie
    problemy, których nie chciałem rozwiązywać w wersji 1.0.

    Ten problem jest rozwiązany w bibliotece YAMI4, ale to zupełnie inna liga.

    > To jest koślawe, sorry. W HTTP masz nie tylko akcje GET i POST, ale i chyba ze 20
    innych.

    Ale ja nie obiecuję obsługi tych 20 innych.

    > Poza tym założenie, że ktoś będzie argumenty POST przesyłał w URL-u jest zdziebko
    przestarzałe, o wiele wygodniej jest słać parametry w JSONie.

    Przecież właśnie tak jest. Dlatego funkcje dla POST mają dodatkowy argument istream -
    tam są te dane, które normalni ludzie przekazują.

    I właśnie dlatego funkcje dla GET i POST *różnią się* sygnaturami.

    > Pamiętanie o kilku wariantach funkcji nie jest prostsze. Już lepiej byłoby mieć
    jedną przeciążoną metodę register i kilka pomocniczych funkcji w stylu
    "make_get_action".

    Czyli że:

    register(make_get_action(my_action));

    jest lepsze od:

    register_get_action(my_action);

    Sorry - ani trochę.

    > > A po co? Bez przesady z tą walidacją. Walidować należy input z zewnątrz (i nawet
    opisałem to w przykładzie 3, z parametrami) a nie własne literały.
    >
    > Bo programista się czasem myli, więc powinien się koncentrować na błędach w kodzie,
    który pisze, a nie którego używa.

    Ale dlaczego ma się koncentrować na błędach w kodzie, którego używa, skoro takich nie
    znalazł a za to ma błędy w swoim? :-)

    I czym się różni pomyłka polegająca na użyciu pustego wskaźnika od pomyłki
    polegającej na użyciu wskaźnika do niewłaściwej funkcji?
    Otóż niczym się nie różni - a kompleksowe rozwiązanie tego zagadnienia (czyli
    zapewnienie, że programista sięgnął po właściwą funkcję) nie leży po stronie użytej
    biblioteki. To jest jedno z częstych nieporozumień w temacie weryfikacji albo
    defensywnego kodowania.

    Na tej podstawie zakładam, że programista poda wskaźnik do właściwej funkcji. To
    założenie jest częścią kontraktu tej biblioteki.

    > > A jakieś inne testy byś chciał?
    >
    > Np. testy jednostkowe parserów, których jest co najmniej ze 2. Jak widzę
    > 5-krotnie zagnieżdżony kod, to nie wiem, czego się spodziewać.

    Uwaga, szpan: pokrycie strukturalne zapewniłem testami systemowymi.

    Bez przesady z tymi testami.

    --
    Maciej Sobczak * http://www.inspirel.com

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: