eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › Embedded HTTP Server
Ilość wypowiedzi w tym wątku: 42

  • 11. Data: 2020-06-07 21:46:34
    Temat: Re: Embedded HTTP Server
    Od: Maciej Sobczak <s...@g...com>

    > Niby tak, ale już cooperative tak nie obskoczysz.

    I naiwna abstrakcja wątków też by mi tego nie dała.

    > Ponadto praktyka pozkauje że zmiana "jednej linijki" w biblitece nie
    > jest prawidłową metodą dopasowania się do czegoś bo za chwile tej
    > linijki nie będzie w wersji 0.9.3.

    I tu płynnie przechodzimy do pytania o to, gdzie jest właściwy poziom abstrakcji. Bo
    Ty chciałbyś, żeby w bibliotece HTTP była abstrakcja wątków na wypadek portowania na
    inną platformę. A ja pytam, dlaczego cały serwer HTTP nie miałby być tą abstrakcją, z
    różnymi implementacjami na różne platformy?

    Cała ta biblioteka ma dokładnie 2 pliki .cpp. Słownie: dwa. Plus 2 headery do nich. I
    działa na Lin/Mac/Win. Dołożenie do niej abstrakcji na okoliczność egzotycznych
    platform wbudowanych z pół-wątkami i dziwacznymi stosami TCP spowodowałoby, że tych
    plików byłoby 10. Albo 30.
    I nawet nie wiem, jaka jest realna nisza rynkowa z takimi potrzebami i czy ona w
    ogóle jest. Bo nisza na wersję 1.0 jest na pewno, bo w szczególności ja sam tego
    użyję. Natomiast te abstrakcje rozwiązałyby problem ludzi o których nawet nie wiem,
    czy istnieją.

    A nie lepiej poczekać, aż ktoś *realnie* zgłosi taką potrzebę i wtedy zrobić port
    tych dwóch plików z zachowaniem API całego serwera HTTP? I wtedy taki port też będzie
    miał 2 pliki .cpp. I ani kawałka kodu więcej.

    Tak, będzie parę linijek zduplikowanych. Ale przekonaj mnie teraz, że koszt tych
    wszystkich abstrakcji jest mniejszy.

    > To tylko łatwo w teorii, w normalnych systemach "podmienianie"
    > std::whatever to jest *gruby* hacking...

    Ale przecież nie pisałeś o normalnych systemach. :-)
    Na normalnych to wszystko działa out-of-the-box i nie trzeba nic hacking.

    > Niby tak, ale znowu: co dziwnego w tym że robisz własną abstrakcję do
    > "ich" abstrakcji?

    A co dziwnego w tym, że ich nie robię i zamiast tego proponuję minimalne rozwiązanie
    dla 99.9% potencjalnych odbiorców?

    > Piszesz rdzeń HTTP w oderwaniu kompletnym od tego jaki stos TCP używasz.

    Przecież tak jest teraz. Dlatego są tam dwa pliki .cpp. Jeden to rdzeń HTTP a drugi
    to IOStreams na "typowym" stosie TCP.

    > *wszystkie* interfejsy GUI jakie istnieją w sensownym zastosowaniu są
    > event-based czyli takie coroutines/cooperative.

    To ciekawa uwaga. W tej bibliotece nie ma na wierzchu niczego podobnego do kolejki, a
    co za tym idzie nie zmusza się użytkownika do kręcenia własną pętlą zdarzeń. Pod tym
    względem ta biblioteka bardziej przypomina lekki framework komunikacyjny, niż typowy
    framework GUI. Ale to dobry zbieg okoliczności, bo akurat HTTP jest protokołem
    komunikacyjnym. A kolorowe jarmarki na display'u i tak zrobisz w JS.

    Czyli zamiast odpowiadać na pytanie jak zrobić GUI, odpowiadamy na pytanie, jak
    zrobić komunikację z tym czymś co robi GUI[*].

    [*] I bez ograniczania się tylko do tego zastosowania (chociaż GUI było motywacją).
    HTTP może służyć również do innych rzeczy, niż GUI. I dlatego też to się nazywa
    "Embedded HTTP Server" a nie "GUI Framework".

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


  • 12. Data: 2020-06-07 23:21:03
    Temat: Re: Embedded HTTP Server
    Od: heby <h...@p...onet.pl>

    On 07/06/2020 21:46, Maciej Sobczak wrote:
    > I tu płynnie przechodzimy do pytania o to, gdzie jest właściwy poziom abstrakcji.
    Bo Ty chciałbyś, żeby w bibliotece HTTP była abstrakcja wątków na wypadek portowania
    na inną platformę. A ja pytam, dlaczego cały serwer HTTP nie miałby być tą
    abstrakcją, z różnymi implementacjami na różne platformy?

    Ależ oczywiscie, przecież normalne jest że bibliteka zaczyna się od
    czegoś w rodzaju:

    IHttpServer* Factory::createServer(
    getTcpStreamsAbstractFactory()
    , getAbstractThreadsPoolFactory()
    , ConcurencyModel::Threaded
    );

    To ja decyduje jakie abstrakcjie to TCP i wątków dostarcze. Moge
    dostarczyć Twoje np. oparte o std::, o ile je napiszesz, ale mogę
    dostarczyć moje oparte o gołe FreeRTOS albo własny scheduler. Ja
    decyduje czy chcę wątki a jak chce to jakie, nic o tym nie musisz wiedzieć.

    > Cała ta biblioteka ma dokładnie 2 pliki .cpp. Słownie: dwa. Plus 2 headery do nich.
    I działa na Lin/Mac/Win. Dołożenie do niej abstrakcji na okoliczność egzotycznych
    platform wbudowanych z pół-wątkami i dziwacznymi stosami TCP spowodowałoby, że tych
    plików byłoby 10. Albo 30.

    Co złego w plikach ;) Myślałem że czasy MSDOSa słusznie minęły :)

    > I nawet nie wiem, jaka jest realna nisza rynkowa z takimi potrzebami i czy ona w
    ogóle jest.

    Nie ma. Sporo piszesz jeszcze jedną biblioteczkę do http to chyba nie po
    to aby zarabiać. Obecnośc niszy nie ma znaczenia.

    > Bo nisza na wersję 1.0 jest na pewno, bo w szczególności ja sam tego użyję.
    Natomiast te abstrakcje rozwiązałyby problem ludzi o których nawet nie wiem, czy
    istnieją.

    Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący go,
    nie wezmą tej bibliteki. Ponieważ nie napiszą Ci że coś jest potrzebne
    będziesz miał fałszywe przeswiadczenie że nikomu to nie jest potrzebne.

    Taki przykład: embedowanie engine tcl-a do własnego kodu powoduje ze do
    dyspozycji masz *tylko* blokującą funkcję która wygląda tak:

    Tcl::doEverything()
    {
    while( finished( ) )
    Private::doSomething();
    }

    Najlepsze że ta funkcja pojawiła się po tym jak wypruli sobie żyły aby
    zrobic stackless wersję. Efektem czego cały sens stackless (ja
    kontroluje stack) został zaprzepaszczony bo jakiś miszczu założył "komu
    to potrzebne, dajmy mu pętlę, będzie miał łatwiej" i nie da się z nigo
    korzystać jak ze stackless. Interweniowałem na grupie, czy nie mogli by
    udostepnić doSomething() ale dowiedziałem się że "na co to komu". Teraz
    widzisz? Jak nie ma ficzera to do czasu aż nie pojawi się jakiś
    pieniacz, jak ja, autorzy mogą żyć w błednym przekonaniu że "na co to
    komu". A akurat mi to jest potrzebne (i emuluje to przez boost::context,
    innymi słowy używam armaty na muchy).

    > A nie lepiej poczekać, aż ktoś *realnie* zgłosi taką potrzebę i wtedy zrobić port
    tych dwóch plików z zachowaniem API całego serwera HTTP?

    Jeśli prawidłowych abstrakcji nie zrobi się odpowiednio wcześnie to
    potem ciągnięcie koncepcji "no ale przecież są wątki" staje się
    nierefaktorowalne, bo tego typu koncepcje przeciekają do api usera w
    postaci jakiś zdeformowanych wzorców uzycia pasujacych do wątków ale nie
    pasujacych do event based. Potem tylko pozostaje powiedzieć "sorry" i tyle.

    > Tak, będzie parę linijek zduplikowanych. Ale przekonaj mnie teraz, że koszt tych
    wszystkich abstrakcji jest mniejszy.

    Koszt abstrakcji jest kosztem początkowym. Jeśli potrzeba pojawia się
    później (a w zasadzie, jeśli autor po prostu nie zakładał że ona
    istnieje na poczatku) to koszt jest wyższy z powodu długu
    technologicznego który rośnie wraz z każda linią napisaną bez
    prawidłowych abstrakcji.

    >> To tylko łatwo w teorii, w normalnych systemach "podmienianie"
    >> std::whatever to jest *gruby* hacking...
    > Ale przecież nie pisałeś o normalnych systemach. :-)

    Piszę o róznych rzeczach. Gdybym pisał na FreeRTOS to ogólnie nie uzyje
    czegokolwiek z std::thread z racji braku implementacji std::. Jeśli
    piszę jako embedded server w środku mojej aplikacji to mimo posiadania
    std::threads mogę, z jakiejś przyczyny, nie chcieć ich użyć. Na przykład
    z powodu tego że threads powodują spory spadek wydajności, albo np. z
    powodu tego że mam system RT i nie mogę zakładać że jakieś przypadkowe
    wątki uszkadzają mi cache latency albo przerwią ważny algorytm RealTime,
    itd itp.

    > Na normalnych to wszystko działa out-of-the-box i nie trzeba nic hacking.

    Wtedy można się zastanowić dlaczego miałbym brać takie *coś* zamiast
    QtHttpServer?

    >> Niby tak, ale znowu: co dziwnego w tym że robisz własną abstrakcję do
    >> "ich" abstrakcji?
    > A co dziwnego w tym, że ich nie robię i zamiast tego proponuję minimalne
    rozwiązanie dla 99.9% potencjalnych odbiorców?

    Nic. Tak wybrałeś. To nie są zarzuty i nie nakłaniam Cie do zmiany.
    Prosiłeś o uwagi, nie miej pretensji że ktoś je zgłasza i argumentuje
    prowadząc normalną dyskusję. Ja nic nie zarzucam, ale skoro jest
    przestrzeń do dyskutowania to przecież usenet po to powstał

    >> *wszystkie* interfejsy GUI jakie istnieją w sensownym zastosowaniu są
    >> event-based czyli takie coroutines/cooperative.
    > To ciekawa uwaga. W tej bibliotece nie ma na wierzchu niczego podobnego do kolejki,
    a co za tym idzie nie zmusza się użytkownika do kręcenia własną pętlą zdarzeń.

    Ale zmusza to czekania na threads::join oraz używania w kodzie który
    jest GUIoty synchroniacji między wątkami bo callbacki są threaded.
    Innymi słowy Twoja bibliteka wymusiła pojawienie się w kodzie GUI
    synchronizacji która tam jest zbędna.

    Coroutines -> musisz kręcić jakimś server->next()
    Wątki -> musisz synchronizować callbacki z i do bibloteki.

    Ani jedno ani drugie nie jest lepsze. Ale mają coroutines można dodać
    wątki w trywialny sposób. Mając wątki można, ale to bardzo naciągane,
    próbować robić kieskie coroutines z masą hazardów i kiepskim unit
    testowaniem.

    Przy czym to moja opinia. Opieram ją o pewne doświadczenia które trudno
    nazwać obiektywnymi.

    > Pod tym względem ta biblioteka bardziej przypomina lekki framework komunikacyjny,
    niż typowy framework GUI.

    To nie ma znaczenia co przypomina. Jeśli używa wątków i ma callbacki to
    warstwa poniżej musi synchronizować dostęp do zasobów.

    Innymi słowy programista GUI będzie musiał odizolować Twoją biblotekę
    masa wrapperów które ukryją wątkowość Twojej bibloteki jeśli nie chce
    aby mutexy rozlazły się po całym kodzie GUI.

    > Czyli zamiast odpowiadać na pytanie jak zrobić GUI, odpowiadamy na pytanie, jak
    zrobić komunikację z tym czymś co robi GUI[*].

    GUI (natywne) nie lubi jeśli ktoś komunikuje się z nim przez wątki. To
    powoduje masę problemów ponieważ wszystkie najważniejsze frameworki
    GUIowe na normalne maszyny zakładają model jednowątkowy na poziomi API
    systemowego. Więc jeśli budujesz apliakcję na komputer w którym jest GUI
    natywne, powiedzmy w Gtk i jednocześnie w tle apliakcji pracuje sobie
    Twój web server to właśnie dostałeś w prezencie wątki których wcale byc
    nie musi.

    > [*] I bez ograniczania się tylko do tego zastosowania (chociaż GUI było motywacją).
    > HTTP może służyć również do innych rzeczy, niż GUI. I dlatego też to się nazywa
    "Embedded HTTP Server" a nie "GUI Framework".

    Możliwe że się nie rozumiemy w kwestii GUI. Ja mam na myśli GUI w
    programie w którym ktoś wembedował również Twój HTTP. Dzięki temu
    aplikacja GUIowa, mimo że z wątkami ma 0 wspolnego, kiedy komunikuje się
    z Twoim kodem, musi zarządzać hazardami. W przypadku coroutines/events
    nie musi, a jesli chce mieć wątki to ich świadomie używa a jeśli nie
    chce to ma ładne event based, pasujace do reszty interfejsy. I co gorsza
    takich gotowców jest od cholery a dyski i pamięc tania ...


  • 13. Data: 2020-06-08 09:49:49
    Temat: Re: Embedded HTTP Server
    Od: Maciej Sobczak <s...@g...com>


    > Ależ oczywiscie, przecież normalne jest że bibliteka zaczyna się od
    > czegoś w rodzaju:
    >
    > IHttpServer* Factory::createServer(
    > getTcpStreamsAbstractFactory()
    > , getAbstractThreadsPoolFactory()
    > , ConcurencyModel::Threaded
    > );

    Eee... Nie, to nie jest normalne. To jest overengineering.
    Takich rzeczy mógłbym się być może spodziewać w kombajnach typu Boost, gdzie
    jednocześnie mam od razu gotowe do wyboru fafnaście implementacji tych
    polityk/aspektów, oraz oczywiście sensowne defaulty, żebym mógł po prostu napisać
    createServer(). Ale w luźnych bibliotekach to jest overengineering.

    > To ja decyduje jakie abstrakcjie to TCP i wątków dostarcze.

    I nadal kogoś nie zadowolisz, bo parametryzowany mógłby być jeszcze sam protokół albo
    w ogóle fakt istnienia jakiegokolwiek protokołu, szyfrowanie transmisji i jaką
    metodą, alokator pamięci, metoda zamazywania zwolnionej już pamięci (bo jeszcze ktoś
    podejrzy), i w ogóle kto powiedział, że to jest komunikacja TCP a nie serial po USB
    albo przez Bluetooth i jeszcze pierdylion innych rzeczy, o których w poniedziałek
    rano nie chce mi się myśleć.
    I to wszystko to jest overengineering.

    > Co złego w plikach ;) Myślałem że czasy MSDOSa słusznie minęły :)

    Ale wtedy nie dałoby się napisać, że biblioteka ma 2 pliki. :-)

    > > I nawet nie wiem, jaka jest realna nisza rynkowa z takimi potrzebami i czy ona w
    ogóle jest.
    >
    > Nie ma. Sporo piszesz jeszcze jedną biblioteczkę do http to chyba nie po
    > to aby zarabiać. Obecnośc niszy nie ma znaczenia.

    Bingo. Ale skoro cel był inny, to ja ten cel chcę osiągnąć minimalnym kosztem.

    > Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący go,
    > nie wezmą tej bibliteki.

    Moje obserwacje: ludzie unikają potworów, których nie potrzebują. Zamiast tego
    sięgają po proste rozwiązania, które z przyzwyczajenia wloką ze sobą przez swoją
    karierę, zmuszając je do wzrastania razem z nimi i stawania się potworami w sposób
    organiczny.
    Czyli nie feature-bang, tylko raczej feature-creep.

    > Taki przykład: embedowanie engine tcl-a do własnego kodu

    Tak, jesteś wyjątkiem od reguły. :-)

    > Jeśli prawidłowych abstrakcji nie zrobi się odpowiednio wcześnie

    Odpowiednią abstrakcją jest rozwiązanie, któro jest proste.

    > Koszt abstrakcji jest kosztem początkowym.

    Ale nie wiesz jeszcze, które będą potrzebne. Więc wbrew pozorom to też jest
    zaciągnięciem długu. Coś jak kupowanie wszystkich możliwych gadżetów wakacyjnych gdy
    nie wiesz jeszcze, gdzie pojedziesz (i czy w ogóle).

    > Wtedy można się zastanowić dlaczego miałbym brać takie *coś* zamiast
    > QtHttpServer?

    Bo skoro masz Qt, to nie będziesz robił GUI przez HTTP?
    Idea jest taka, żebyś nie musiał mieć Qt.

    > Prosiłeś o uwagi, nie miej pretensji że ktoś je zgłasza

    W żadnym razie nie mam. Ani jednej. W ogóle cieszę się, że ktoś jeszcze żyje na tej
    grupie. To dobra dyskusja, bo porusza ciekawe zagadnienia z teologii projektowania
    produktów. Nie tylko programistycznych. Czy lepiej jest zrobić nożyk czy scyzoryk
    szwajcarski? Przecież nożyk nie ma prawidłowych abstrakcji pozwalających z niego
    zrobić zestaw dentystyczny. A jednak nożyki idą jak woda - właśnie dlatego, że nie
    atakują użytkownika abstrakcjami, których nie potrzebuje.

    > Innymi słowy Twoja bibliteka wymusiła pojawienie się w kodzie GUI
    > synchronizacji która tam jest zbędna.

    Nie wymusiła i nie jest zbędna. To użytkownik decyduje, jak tego użyje. W przykładach
    synchronizacja pojawiła się dopiero w ostatnim (6. SSE) i właśnie ten przykład można
    napisać inaczej, np. włączając wywołanie akcji HTTP we własną kolejkę zdarzeń.

    > Coroutines -> musisz kręcić jakimś server->next()
    > Wątki -> musisz synchronizować callbacki z i do bibloteki.

    Tak. Np. w bibliotece YAMI4 są dwa poziomy API. Niższy to tzw. core, gdzie trzeba
    wołać funkcję agent.do_some_work(). Wyższy to tzw. high-level, gdzie "samo lata".
    I zgadnij, czego ludzie używają.

    > Ani jedno ani drugie nie jest lepsze.

    Zgadza się. Więc jeśli będzie potrzeba, to biblioteka HTTP w wersji eventowej też
    powstanie. Ale na razie nie potrzeba.

    > GUI (natywne) nie lubi jeśli ktoś komunikuje się z nim przez wątki.

    Tu nie ma natywnego GUI.

    > Więc jeśli budujesz apliakcję na komputer w którym jest GUI
    > natywne, powiedzmy w Gtk i jednocześnie w tle apliakcji pracuje sobie
    > Twój web server to właśnie dostałeś w prezencie wątki których wcale byc
    > nie musi.

    Ale których obecność nie musi być problemem.
    Ciekawe - przez 30 lat wszyscy mieli pretensje do C++, że nie ma standardowych
    wątków. Teraz ma i jest problem, że są?

    > Możliwe że się nie rozumiemy w kwestii GUI. Ja mam na myśli GUI w
    > programie w którym ktoś wembedował również Twój HTTP.

    A ja progam, który tego klasycznego GUI już nie ma. Ale niech będzie, że ma.

    > Dzięki temu
    > aplikacja GUIowa, mimo że z wątkami ma 0 wspolnego,

    Ja jeszcze nie widziałem takiej aplikacji (pomijam przykłady typu kalkulator z
    tutoriala do tegoż GUI).
    W aplikacjach, które widziałem, na potrzeby GUI był przeznaczony 1 z N wątków tejże
    aplikacji. I było M powodów, żeby właśnie tak zrobić.

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


  • 14. Data: 2020-06-08 10:32:58
    Temat: Re: Embedded HTTP Server
    Od: Mateusz Viste <m...@x...invalid>

    2020-06-07 o 23:21 +0200, heby napisał:
    > Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący
    > go, nie wezmą tej bibliteki. Ponieważ nie napiszą Ci że coś jest
    > potrzebne będziesz miał fałszywe przeswiadczenie że nikomu to nie
    > jest potrzebne.

    A jednak ja co rusz dostaję jakieś prośby o dodatkowe funkcje i sugestie
    dot. moich programów... Twoja teoria się nie sprawdza :)
    Oczywiście może być tak jak piszesz, ale tylko w sytuacji, kiedy
    istnieje szeroki wybór alternatyw i jest coś, co pasuje idealnie do
    potrzeby użytkownika. Ale w takim wypadku niech faktycznie bierze to
    coś innego co mu pasuje idealnie i nie zawraca dupy.

    Mateusz


  • 15. Data: 2020-06-08 11:39:27
    Temat: Re: Embedded HTTP Server
    Od: Wojciech Muła <w...@g...com>

    On Saturday, June 6, 2020 at 8:34:11 PM UTC+2, Maciej Sobczak wrote:
    > > file_mime_type("html") zwróci "text/html" zamiast "text/plain"
    >
    > To dobrze? Źle? Jak powinno być i dlaczego?

    Jeśli przyjmujesz, że to rozszerzenie pliku determinuje typ MIME, to nazwa "html" nie
    posiada rozszerzenia.

    w.


  • 16. Data: 2020-06-08 11:52:33
    Temat: Re: Embedded HTTP Server
    Od: heby <h...@p...onet.pl>

    On 08/06/2020 09:49, Maciej Sobczak wrote:
    >> To ja decyduje jakie abstrakcjie to TCP i wątków dostarcze.
    > I nadal kogoś nie zadowolisz, bo parametryzowany mógłby być jeszcze sam protokół
    albo w ogóle fakt istnienia jakiegokolwiek protokołu, szyfrowanie transmisji i jaką
    metodą, alokator pamięci, metoda zamazywania zwolnionej już pamięci (bo jeszcze ktoś
    podejrzy), i w ogóle kto powiedział, że to jest komunikacja TCP a nie serial po USB
    albo przez Bluetooth i jeszcze pierdylion innych rzeczy, o których w poniedziałek
    rano nie chce mi się myśleć.

    Nie, to wszystko jest w implementacji IStream :D A raczej może być i nie
    Ty to piszesz.

    >> Jeśli nie zaimplementujesz jakiegoś ficzera to ludzie potrzebujący go,
    >> nie wezmą tej bibliteki.
    > Moje obserwacje: ludzie unikają potworów, których nie potrzebują. Zamiast tego
    sięgają po proste rozwiązania, które z przyzwyczajenia wloką ze sobą przez swoją
    karierę, zmuszając je do wzrastania razem z nimi i stawania się potworami w sposób
    organiczny.
    > Czyli nie feature-bang, tylko raczej feature-creep.

    Ale czyż nie myślisz o tym aby zmieniac świat czy może już przekroczyłeś
    20tkę i zastanawiasz się jak dotrwać do emerytury :D ?

    >> Jeśli prawidłowych abstrakcji nie zrobi się odpowiednio wcześnie
    > Odpowiednią abstrakcją jest rozwiązanie, któro jest proste.

    Nie, to nie abstrakcja. Powiedzmy że abstrakcja to nie dawanie w
    gratisie implementacji które autorowu wydają się być prawidłowe.

    >> Koszt abstrakcji jest kosztem początkowym.
    > Ale nie wiesz jeszcze, które będą potrzebne. Więc wbrew pozorom to też jest
    zaciągnięciem długu. Coś jak kupowanie wszystkich możliwych gadżetów wakacyjnych gdy
    nie wiesz jeszcze, gdzie pojedziesz (i czy w ogóle).

    Tu tylko chodzi o gadget IAbstractStreamFactory i IAbstractThreadFactory.

    Innymi słowy wybieram się na wakacje z gotówką portfelui i kupie sobie
    na miejscu co mi jest potrzebne, vs rozwiązanie kiedy wybierając sie w
    góry mam bagażnik zawalony pontonami bo autor biblioteki lubi morze.

    >> Wtedy można się zastanowić dlaczego miałbym brać takie *coś* zamiast
    >> QtHttpServer?
    > Bo skoro masz Qt, to nie będziesz robił GUI przez HTTP?

    Może będę. W końcu to *embedded* server, więc dlaczego miałbym go nie
    zaembedować robiac jakąs apliakcję z wielodostępem? Abecnie dziubdziam
    hobbystycznie aplikacje z lokalnym GUI i jednoczesnym dostępem przez
    www, konkretnie to kontroler falownika.

    > Idea jest taka, żebyś nie musiał mieć Qt.

    Jak masz gazyliony bajtów to Qt jest najmniejszym problemem. Widuje
    aplikacje z kodem kilkaset kB + grube setki MB na Qt tylko po to aby
    wyświetlić okienko z przyciskiem. Uchodzi, jak widać.

    >> Innymi słowy Twoja bibliteka wymusiła pojawienie się w kodzie GUI
    >> synchronizacji która tam jest zbędna.
    > Nie wymusiła i nie jest zbędna. To użytkownik decyduje, jak tego użyje.

    Właśnie nie. "kuźwa, znowu mutexy" i takie klimaty.

    > W przykładach synchronizacja pojawiła się dopiero w ostatnim (6. SSE) i właśnie ten
    przykład można napisać inaczej, np. włączając wywołanie akcji HTTP we własną kolejkę
    zdarzeń.

    Innymi słowy emulujesz coroutines/events na bazie wątków.

    > Tak. Np. w bibliotece YAMI4 są dwa poziomy API. Niższy to tzw. core, gdzie trzeba
    wołać funkcję agent.do_some_work(). Wyższy to tzw. high-level, gdzie "samo lata".
    > I zgadnij, czego ludzie używają.

    To nie kwestia czego używa większosc tylko czy można uzyć tego w sposób
    niestandardowy. Właśnie to powodujee że nagle ten promil programistów
    powie "no właśnie czegoś takiego szukam od 10 lat, genialne". A reszta
    nie zauważy róznicy bo dostanie implementacje wątkową jako domyślną.
    Wszyscy zadowoleni.

    > Zgadza się. Więc jeśli będzie potrzeba, to biblioteka HTTP w wersji eventowej też
    powstanie. Ale na razie nie potrzeba.

    Błedne koło, nikt takiej nie potrzebuje bo wszyscy robią to na wątkach i
    nie potrzebuja już eventów mają dawno architekturę z workaroundami na
    wątki żeby zachowywyały się jak eventy itd itp.

    > Ale których obecność nie musi być problemem.
    > Ciekawe - przez 30 lat wszyscy mieli pretensje do C++, że nie ma standardowych
    wątków. Teraz ma i jest problem, że są?

    Nie, problem że jak się pojawiły to nagle okazuje się że można je
    wstawić wszędzie. Kilka lat temu widziłem gdzies biblitekę do liczenia
    jakiś protych rzeczy na futures/promises. Kiedy kurz opadł okazało się
    że jest dziesiątki razy mniej wydajna niż cokolwiek typu coroutine.
    Wybacz, nie pamietam już co to było, coś do obliczeń tensorowych, chyba
    z AI. Człowiek nie rozumiał że zrobienie future z return a+b; mija się z
    celem.

    >> Dzięki temu
    >> aplikacja GUIowa, mimo że z wątkami ma 0 wspolnego,
    > Ja jeszcze nie widziałem takiej aplikacji (pomijam przykłady typu kalkulator z
    tutoriala do tegoż GUI).

    Cały Win3.11, wcześny MacOS oraz prawie każdy exampl (a one bywaj
    ogromne) na Qt to takie przykłady z brzegu gdzie multitasking jest a
    wątków preemptive brak i całkiem do rzeczy to działa.

    > W aplikacjach, które widziałem, na potrzeby GUI był przeznaczony 1 z N wątków tejże
    aplikacji. I było M powodów, żeby właśnie tak zrobić.

    Apliakcji bez wątków, responsywnych i wygodnych, jest też sporo. Wątki w
    zasadzie są użyteczne w sytuacjach kiedy nie masz kontroli nad kodem i
    musisz go puścić na żywioł. Kiedy masz kontrole zawsze można zrobić
    fibers/coroutines i obejść problem drogiego synchronizowania danych i
    przełączania kontekstu. Oczywiście każdy przypadek wymaga analizy, ale
    nie twierdziłbym kategorycznie że apliakcja GUI musi mieć wątki. Prawa
    jest taka że czasem musi bo kod jest tak kiepski że nie da się inaczej.
    Jak choćby ten nieszczęsny tcl gdzie dev dodał "while() {}" bo dzięki
    temu masz *uproszczone* sterowanie. Qźwa go mać.


  • 17. Data: 2020-06-08 12:25:57
    Temat: Re: Embedded HTTP Server
    Od: Wojciech Muła <w...@g...com>

    On Saturday, June 6, 2020 at 9:00:07 PM UTC+2, Maciej Sobczak wrote:
    > > Po pierwsze, to aż się prosi, żeby ten serwer był zwykłą klasą. Czemu ktoś nie
    miałby sobie stworzyć 5 serwisów WWW działających na różnych portach?
    >
    > No właśnie. I tu poruszamy ważną kwestię. Bo piszesz, że aż się prosi, ale potem
    okazuje się, że nikt nie prosi, tylko czemu ktoś by miał nie prosić.

    Czyli ograniczasz użytkowników do jednego przypadku i to w sytuacji, gdy dodanie
    jednego stopnia swobody nie kosztuje ani użytkownika, ani Ciebie nic.

    > A mi chodziło o to, żeby pakiet 1.0 przekroczył próg używalności a nie o to, żeby
    rozwiązać problemy typu "czemy ktoś nie miałby".

    Żeby Twojego rozwiązania użyć w jakimś normalnym programie, trzeba stworzyć wątek.
    Wygodne użycie, to byłoby coś takiego:

    int main() {
    auto server = std::make_unique<http::Server>(8008, ".");

    // tu sobie programista coś inicjalizuje

    server->start();

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

    > 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. A, że masz ją współdzieloną, to też masz
    radosnego mutexa w głównej pętli.

    > > Po drugie, nie ma sposobu na zamknięcie serwera, poza zabiciem procesu. Chyba, że
    ja czegoś nie widzę.
    >
    > Tak. Funkcja server_stop() już istniała, ale ją usunąłem. To nie jest oczywiste,
    jak zamknąć serwer, który ma callbacki, niektóre zapewne w trakcie pracy.
    > Wszystkie problemy da się rozwiązać, ale nie o to chodziło w wersji 1.0.

    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.

    > > Mówiąc o API: 6 wariantów register_{generic,html,text}_{post,get}_action można by
    sprowadzić do 2. register_action(const char* name, {post_action_type,
    get_action_type} callback, const char* mime_type).
    >
    > Nie, bo po pierwsze generic i html różnią się obsługą a po drugie nie chciałem
    przeciążać funkcji register, bo bardziej naturalne wydaje mi się przeciążenie funkcji
    akcji dla get i post:
    >
    > void my_action(to-co-trzeba-dla-get) { ... }
    > void my_action(to-co-trzeba-dla-post) { ... }
    >
    > I wtedy nie dałoby rady:
    >
    > register(my_action);

    To jest koślawe, sorry. W HTTP masz nie tylko akcje GET i POST, ale i chyba ze 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.

    > > Zresztą, może lepiej byłoby przyjmować jako argument mapę akcji - czyli to co
    masz teraz w get_actions/post_actions. Niech user sobie przygotuje takie mapy w
    sposób, jaki mu pasuje, a ty pozbędziesz się potrzeby blokowania tych struktur.
    >
    > Ale teraz obsługa jest prostsza, właśnie dlatego, że user nie musi robić takich
    map.

    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".

    > Można by było pomyśleć o akcji catch-all. Tam user dostawałby wszystko (co nie było
    obsłużone) i mógłby sobie tam zrobić takie mapy, jakie zechce.
    >
    > > Czasem funkcje przyjmują const char*, czase std::string& co jest niespójne.
    >
    > Bo chodziło o przewidywane użycie. Tam gdzie przewidywałem literał, jest const
    char*.

    const char* to nie tylko literały, tego założenia nie da się odczytać z API.

    > > W ogóle nie walidujesz, czy wskaźniki są niepuste. Tak samo z std::function.
    >
    > 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.

    > > Zero testów. Serio? :)
    >
    > Są testy. W katalogu, który dla zmylenia przeciwnika nazywa się examples. :-)
    >
    > 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ć.

    w.


  • 18. Data: 2020-06-08 20:33:42
    Temat: Re: Embedded HTTP Server
    Od: Maciej Sobczak <s...@g...com>

    > > To dobrze? Źle? Jak powinno być i dlaczego?
    >
    > Jeśli przyjmujesz, że to rozszerzenie pliku determinuje typ MIME, to nazwa "html"
    nie posiada rozszerzenia.

    Dalej nie rozumiem. Nazwa "html" nie posiada rozszerzenia, ale "index.html" jak
    najbardziej posiada i jest nim "html" i wtedy typ jest "text/html".

    Czy chodziło o coś innego?

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


  • 19. Data: 2020-06-08 21:20:38
    Temat: Re: Embedded HTTP Server
    Od: Maciej Sobczak <s...@g...com>

    > Ż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


  • 20. Data: 2020-06-08 21:32:08
    Temat: Re: Embedded HTTP Server
    Od: heby <h...@p...onet.pl>

    On 08/06/2020 21:20, Maciej Sobczak wrote:
    > 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?

    Na tym że pierwsa jest wykrywana przez trywialny assert. Nie użycie go
    świadczy o bardzo kiepskiej jakości kodzie ponieważ bibiloteka nawet
    *takiej* oczywistości nie weryfikuje, a powinna weryfikować jak nawięcej
    (w debugu).

    > Otóż niczym się nie różni

    Z praktyki wynika że nullowe pointery są znacznie wiekszym problemem niż
    niewłaściwe pointery, bo te drugie często załatwia się kontrolą typów.
    Szczególnie kiedy biblitekę używasz po raz pierwszy i spodziewasz się
    choć odrobiny wsparcia po jej stronie.

    > Bez przesady z tymi testami.

    Nie wykluczam że w projaktach hobbystycznych jest jakiś margines
    projektów gdzie faktycznie psu na budę te testy. Skoro taki masz target...

strony : 1 . [ 2 ] . 3 ... 5


Szukaj w grupach

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: