abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 16:11 | Nová verze

    Bylo oznámeno (cs) vydání Fedora Linuxu 40. Přehled novinek ve Fedora Workstation 40 a Fedora KDE 40 na stránkách Fedora Magazinu. Současně byl oznámen notebook Slimbook Fedora 2.

    Ladislav Hagara | Komentářů: 3
    dnes 13:44 | Upozornění

    ČTK (Česká tisková kancelář) upozorňuje (X), že na jejím zpravodajském webu České noviny byly dnes dopoledne neznámým útočníkem umístěny dva smyšlené texty, které nepocházejí z její produkce. Jde o text s titulkem „BIS zabránila pokusu o atentát na nově zvoleného slovenského prezidenta Petra Pelligriniho“ a o údajné mimořádné prohlášení ministra Lipavského k témuž. Tyto dezinformace byly útočníky zveřejněny i s příslušnými notifikacemi v mobilní aplikaci Českých novin. ČTK ve svém zpravodajském servisu žádnou informaci v tomto znění nevydala.

    Ladislav Hagara | Komentářů: 15
    dnes 13:33 | Komunita

    Byla založena nadace Open Home Foundation zastřešující více než 240 projektů, standardů, ovladačů a knihoven (Home Assistant, ESPHome, Zigpy, Piper, Improv Wi-Fi, Wyoming, …) pro otevřenou chytrou domácnost s důrazem na soukromí, možnost výběru a udržitelnost.

    Ladislav Hagara | Komentářů: 0
    dnes 13:00 | Nová verze

    Společnost Meta otevírá svůj operační systém Meta Horizon OS pro headsety pro virtuální a rozšířenou realitu. Vedle Meta Quest se bude používat i v připravovaných headsetech od Asusu a Lenova.

    Ladislav Hagara | Komentářů: 0
    dnes 04:33 | IT novinky

    Společnost Espressif (ESP8266, ESP32, …) získala většinový podíl ve společnosti M5Stack, čímž posiluje ekosystém AIoT.

    Ladislav Hagara | Komentářů: 0
    včera 23:44 | Nová verze

    Byla vydána nová stabilní verze 3.5 svobodného multiplatformního softwaru pro editování a nahrávání zvukových souborů Audacity (Wikipedie). Přehled novinek také na YouTube. Nově lze využívat cloud (audio.com). Ke stažení je oficiální AppImage. Zatím starší verze Audacity lze instalovat také z Flathubu a Snapcraftu.

    Ladislav Hagara | Komentářů: 0
    včera 16:44 | Zajímavý článek

    50 let operačního systému CP/M, článek na webu Computer History Museum věnovaný operačnímu systému CP/M. Gary Kildall z Digital Research jej vytvořil v roce 1974.

    Ladislav Hagara | Komentářů: 2
    včera 16:22 | Pozvánky

    Byl zveřejněn program a spuštěna registrace na letošní konferenci Prague PostgreSQL Developer Day, která se koná 4. a 5. června. Na programu jsou 4 workshopy a 8 přednášek na různá témata o PostgreSQL, od konfigurace a zálohování po využití pro AI a vector search. Stejně jako v předchozích letech se konference koná v prostorách FIT ČVUT v Praze.

    TomasVondra | Komentářů: 0
    včera 03:00 | IT novinky

    Po 48 letech Zilog končí s výrobou 8bitového mikroprocesoru Zilog Z80 (Z84C00 Z80). Mikroprocesor byl uveden na trh v červenci 1976. Poslední objednávky jsou přijímány do 14. června [pdf].

    Ladislav Hagara | Komentářů: 6
    včera 02:00 | IT novinky

    Ještě letos vyjde Kingdom Come: Deliverance II (YouTube), pokračování počítačové hry Kingdom Come: Deliverance (Wikipedie, ProtonDB Gold).

    Ladislav Hagara | Komentářů: 13
    KDE Plasma 6
     (72%)
     (10%)
     (2%)
     (17%)
    Celkem 696 hlasů
     Komentářů: 4, poslední 6.4. 15:51
    Rozcestník

    Dotaz: C - lze poslat soubor i zpravu na server soucasne?

    tomes.io avatar 29.1.2014 21:35 tomes.io | skóre: 12 | blog: tomesh
    C - lze poslat soubor i zpravu na server soucasne?
    Přečteno: 919×
    Ahoj,

    pisu synchronizacni server a klienta. Klient pomoci inotify monitoruje adresar a pri napriklad vytvoreni souboru na to upozorni.

    Klient by mel poslat soubor na server (ten ma vlastni adresar kam si vse uchovava) a server potom soubor posle do vsech ostatnich pripojenych klientu.

    Vim, jak poslat soubor pres socket. Jak ale zaridit, aby server vedel, kam ve strukture sveho adresare (musi byt stejna jak struktura klienta) soubor ulozit a tim padem i kam ve strukture vsech pripojenych klientu.

    Napadlo me, ze by bylo dobre, aby klient poslal soubor a zaroven i zpravu s cestou, kde ve sve adresarove strukture doslo ke zmene (napriklad vytvoreni souboru). Ale jak to udelat? Muj server pri kazdem accept vytvori nove vlakno, takze nemuzu poslat dve zpravy z klienta po sobe...

    Řešení dotazu:


    Odpovědi

    Josef Kufner avatar 29.1.2014 21:49 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Podívej se na formát PNG a třeba i na RTMP nebo SSH File Transfer Protocol. Myslím, že to je celkem dobrá inspirace, jak na to.

    Pointa je, že musíš definovat protokol, kterým budeš přenášet různé zprávy v rámci jednoho spojení. Pak si do takových zpráv můžeš nacpat metadat, co hrdlo ráčí. Na přijímací straně pak potřebuješ události-produkující parser, který bude dostávat surová data a volat callback, když zpráva doběhne do bufferu celá. Na to stačí vcelku jednoduchý konečný automat. Počítej jen s tím, že na jeden fread() ti může přijít jen kousek – proto buffer a automat, který detekuje skutečný konec zprávy.
    Hello world ! Segmentation fault (core dumped)
    tomes.io avatar 29.1.2014 22:46 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Ano, protokol urcite, ale muj dotaz smeroval spise k technickemu reseni:

    muzu napriklad na server poslat zpravu ve tvaru:
    cesta/k/souboru'nulovy byte'soubor
    tim, ze dvakrat po sobe zavolam na socket z klienta write() a az potom zavrit socket? Nejsem si jisty jak v takovem pripade pracuje accept(). Pokud by cekal na uzavreni klientskeho socketu tak by to snad slo ne?

    Nejak pseudo takto:

    Klient:
    write(socket,"cesta")
    write(socket,soubor)
    close(socket)
    
    Tohle by mohlo fungovat pokud accept na strane serveru ceka. Ale nejsem si jisty timto chovanim.
    29.1.2014 22:54 Logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Jojo - accept prostě vytvoří spojení - dvoustrannou rouru - do které se můžou z obou stran lít data a na druhé straně vytečou. Teda defakto jde o dvě jednosměrné roury (tj. když tam nalejí data oba, tak se vprostřed nesmíchaj :-)). Dokonce tam může jít o konverzaci - server si přečte, co poslal klient, něco mu pošle zpět, na to zas odpoví klient atd... Dokud jeden z nich socket nezavře, tak spojení trvá.
    30.1.2014 00:10 Sten
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Jde to takto, a když tam přidáte i délku souboru: cesta/k/souboru NULL délka soubor

    tak můžete posílat i víc souborů v jednom spojení :-)
    tomes.io avatar 30.1.2014 00:44 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Diky, to jsem potreboval vedet, tak to, myslim asi uz nemam problem.

    Jeste jednu doplnujici otazku bych mel:

    Jake jsou obecne dobre zpusoby predavani zprav, trebas i pres printf napriklad, kdyz chci poslat zpravu do sveho systemoveho daemona ve tvaru: caller message

    Muzu napriklad pouzit takovouto fci:
    int sl_log(const char *caller, const char* message) {
        
        int fp;
        fp = open("/tmp/pb173_syslog", O_WRONLY);
        char *msg;
    
        if (fp == -1) {
            perror("Could not open the pipe\n");
            exit(1);
        }
        
        asprintf(&msg, "%s^%s\n", caller, message);
        write(fp, msg, strlen(msg));
        free(msg);
        close(fp);
        return 0;
    } 
    
    Ktera pouziva strisku ^ jako oddelovac aznak pro konec radku jako indikator pro konec zpravy. Jak ale jeste jinak indikovat konec zpravy? V pripade, ze se do jedne message posle treba
    radek1\nradek2\n
    atd. Proste nejake jine oddeleni resp. ukonceni zpravy.
    tomes.io avatar 30.1.2014 00:48 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Muzu teda asi taky poslat NULL, ze? ALe zajima me, zda to jde jeste jinak.
    tomes.io avatar 30.1.2014 11:07 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Tak druha moznost je delka message. Tim se taky zjisti kde zprava skoncila.
    Josef Kufner avatar 30.1.2014 15:21 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Na '\0' pozor, to se může v datech vyskytovat.
    Hello world ! Segmentation fault (core dumped)
    30.1.2014 01:19 cronin | skóre: 49
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Ano, protokol urcite, ale muj dotaz smeroval spise k technickemu reseni:

    muzu napriklad na server poslat zpravu ve tvaru:
    cesta/k/souboru'nulovy byte'soubor
    Je jedno, aký oddeľovač bude použitý, alebo v akej štruktúre budú údaje, môže to byť XML, JSON, alebo kľudne dve bajtové postupnosti oddelené nulovým bajtom, ako je uvedené vyššie. Dôležité je, aby obe strany mali zhodné chápanie - t.j. PROTOKOL - toho, čo sa posiela. Protokol nie je nič viac, ako dohoda o formáte, štruktúre, či postupnosti krokov. No a ak máš pod kontrolou implementáciu na oboch stranách, môžeš si zvoliť vlastný protokol podľa ľubovôle (najmä, ak sa voláš Ľubo, že áno).

    Tak či tak, veci sú zvyčajne jednoduchšie, ak sa použije niečo, čomu rozumejú aj iné nástroje, ako tie Tvoje: riadky textu, CSV, alebo už vyššie zmienený JSON. Napoviem, že binárne údaje možno zakódovať napr. base64, aby sa dali bezpečne prenášať ako text. Nakoniec tak bude možné riešenie - alebo jeho časť - namiesto low-level kódovania v C poskladať v skriptovacom jazyku z existujúcimi nástrojmi.

    Ak však ide o akademickú úlohu a cieľom je naučiť sa práve to, ako to implementovať v C, predchádzajúci odstavec ignoruj, aspoň čo sa týka skriptovania a nástrojov; odporúčanie použiť podľa možnosti existujúci protokol či formát výmeny údajov stále platí.
    Josef Kufner avatar 30.1.2014 10:31 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Opakem k accept() je connect() a opakem k write() je read().

    Volání accept() pouze vyzvedává příchozí spojení, žádná data nečte. Tedy ze serverového filedescriptoru zavoláním accept() oddělíš klientský, který už lze použít ke komunikaci. Všimni si, že ze serverového filedescriptoru nikdy nečteš.

    Když vícekrát zavoláš write(), data jsou uložena do bufferu a následně odesílána klientovi, který je získá pomocí read(). Počet volání read() neodpovídá počtu volání write().

    Co se samotných dat týče, můžeš poslat naprosto cokoliv.

    Pamatuj jen, že pokud se ti ztratí TCP spojení, nemáš nijak garantováno, která data klient přijal a která už se ztratila. Tedy úspěšný write() znamená jen uložení dat do lokálního bufferu, nikoliv jejich doručení.

    Jinak nepoužívej přímo read() a write(), jejich použití není zrovna triviální a má plno temných zákoutí. Raději nejprve zavolej na socket fdopen() a pak použij fread(), fwrite(), fflush() a fclose(). Ušetříš si starosti a podivné chyby.
    Hello world ! Segmentation fault (core dumped)
    30.1.2014 13:05 Ivan
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Spis bych doporucil "Pascalovskou konvenci", tzn nejdrive posli delku v bajtech (treba uint64_t) a teprve pak samotny string. (Jen si musis dat pozor na Indiany).
    tomes.io avatar 30.1.2014 20:52 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Tak jsem se pustil do implementace, ale pada mi to na strane serveru pri fwrite. Je zajimave, ze v netbeans to nepada.

    Klient posila zpravy touto funkci. message je zprava s cestou k souboru (obsahuje pridavne informace a flagy) a path je samotna cesta k souboru. Cilem teto fce je dat dohromady message a obsah souboru a poslat to na server:
    strcat(buf,fbuffer);
    Zprava je ve tvaru:
    flag:je_adresar:delka_nazvu_domovskeho_adresare:delka_cesty:cesta/k/souboru:soubor
    void send_msg(char *message, char *path) {
            
        int len;
        char buf[1024];
        FILE *file;
        char *fbuffer;
        unsigned long fileLen;
    
        strcpy(buf, message);
    
        file = fopen(path, "rb");
        if (!file)
        {
            fprintf(stderr, "Unable to open file %s", message);
            return;
        }
    
        fseek(file, 0, SEEK_END);
        fileLen=ftell(file);
        fseek(file, 0, SEEK_SET);  
        fbuffer=(char *)malloc(fileLen+1);
        if (!fbuffer)
        {
            fprintf(stderr, "Memory error!");
            fclose(file);
            return;
        }
        
        fread(fbuffer, fileLen, 1, file);
        fclose(file);  
        strcat(buf,fbuffer);   
        len = strlen(buf);
        buf[len++] = '\n';
        buf[len] = '\0';
        send(sockfd, buf, strlen(buf), 0);  
        free(fbuffer);
        free(message);
        message = NULL;
    }
     
    
    
    Server zpravu prijime a cely buffer posle na zpracovani do fce, handle_msg, kde se vse rozparsuje (ty printf tam mam zatim jen pro debugovaci ucely). Spadne mi to na:
    File Cannot be opened file on server

    Pritom promenna home (cesta do adresare serveru, kam se prijaty soubor ulozi) se vypise spravne.
    
    void handle_msg(char *buf) {
        
        char *p_str;
        char file[1024];
        char home[1024];
        char path[1024];
        int j;
        int flag;
        int hm_len;
        int par_len;
        int is_dir;
        
        strcpy(home, buf);
            j = 0;
            p_str = strtok(home, ":");
    
        while (p_str != NULL) {
            
                if (j == 0)
                    flag = atoi(p_str);
                else if (j == 1)
                    is_dir = atoi(p_str);
                else if (j == 2)
                    hm_len = atoi(p_str);
                else if (j == 3)
                    par_len = atoi(p_str);
                else if (j == 4)
                    strcpy(path, p_str);
                else
                    strcpy(file, p_str);
                p_str = strtok(NULL, ":");
                j++;
        }
            
        printf("flag: %d\n", flag);
        printf("isdir: %d\n", is_dir);
        printf("hmlen: %d\n", hm_len);
        printf("parlen: %d\n", par_len);
        printf("path: %s\n", path);
            
        memset(home, '\0', sizeof (home));
        strcpy(home,mydir); // mydir je nazev korenoveho adresare serveru
        strcat(home, path + hm_len); //k mydir se prida prislusna cesta - adresarova struktura musi byt stejna u serveru i klienta
            
        printf("home: %s\n", home); //vytiskne se korektne
        
        if ((flag == IN_CREATE)) {
            
            if(is_dir)
                mkpath(home, S_IRWXU | S_IRWXG | S_IRWXO);
            else {
                FILE *fr = fopen(home, "wb");      
                if(fr == NULL)
                    printf("File Cannot be opened file on server.\n"); //fr je z nejakeho duvodu NULL
                    
                fwrite (file , sizeof(char), sizeof(file), fr);   
                fclose(fr);    
            }
        }
    
        
    }
    
    void *thread_reader(void **_client) {
        
        client_t *client = *_client;
        char *buf = NULL;
        int len = 0;
        int i;
        char *rest;
    
        while (1) {
            
            buf = (char *) realloc(buf, len + 1024);
            len += recv(client->fd, buf, 1024, 0);
            for (i = 0; i < len; i++) {
                if (buf[i] == '\n')
                    break;
            }
            
            handle_msg(buf);
            rest = (char *) malloc(len - i);         
            broadcast(client->id, buf, i + 1);
            free(buf);
            buf = rest;
        }
    }
    
    
    Pri oteviran isouboru je file descriptor z nejakeho duvodu NULL a ja netusim vubec proc.

    tomes.io avatar 30.1.2014 22:03 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Mno, asi to bude v neosetreni parsovani, respektive kdyz pridam koncovou nulu do home tak to padat prestane, akorat se mi blbe zkopiruje ten soubor. Sice se v adresari serveru objevi, ale asi nejaky bajt chybi, protoze se neotevrou, linux si jednou mysli, ze se jdna o obrazek (a tak ho zobrazi ve file manageru) nebo skript atd.

    asi mi trosku unika osetreni na urovni bajtu, ale zatim nevim kde.
    tomes.io avatar 30.1.2014 23:31 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    I pres to osetreni mallocu, vysledny zkopirovany soubor je chybny. Bud spatne kopiruji a nasledne ctu soubor, nebo blbe parsuju, nebo vsechno dohromady. Ale uz je pozde, dneska uz toho mam plnou hlavu a asi nic nevymyslim. Snad to zitra bud lepsi.
    30.1.2014 22:10 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    Otvíráš jej pro zápis!, zkus se juknout do errno.

    OT:
    1. objev valgrind
    2. alokace/realokace je třeba testovat Pozor na dost běžný a hloupý zápis k vůli kterému leak-uje spousta programů.
        
      if((buff = realloc(buff,size)) == NULL){
        ...chyba...a...
      }
      
      Když zklame už paměť neuvolníš, takže jedině v případě pokud následuje „bác“ (exit/abort), jinak něco jako:
        
      void *tmp;
      if((tmp = realloc(buff,size)) == NULL){
        ...chyba...a...
        free(buff);/*pokud to tedy neuvolnis nekde jinde*/
        buff=NULL;
        return CHYBA;
      }else buff = (muj_typ*) tmp;
      
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    30.1.2014 22:14 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    3. Možná je bezva nápad: strcpy(home, buf); nahradit: strncpy(home, buf, 1023); home[1023]='\0';
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 30.1.2014 22:43 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    No vsak ano. V klientovi, kde potrebuji nacist soubor ho oteviram pro cteni:
    file = fopen(path, "rb");
    a v serverum kde ho chci vytvorit, ho oteviram pro (vytvoreni a)zapis:
    FILE *fr = fopen(home, "wb");

    Co je na tom spatne?
    30.1.2014 22:55 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Nic, nestudoval jsem to, psal jsi, že ti to zklame, tak jsem se tam podíval 'fr' mi evokovalo „FileRead“.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 30.1.2014 23:00 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Je to matouci pravda, radsi to prepisu na fw :)
    Josef Kufner avatar 31.1.2014 00:56 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Obsah souboru není null-terminated string! Na taková data nemůžeš používat strcpy, ale jen memcpy. Také je nesmysl přidávat nulu na konec, neboť tím zmršíš výsledný soubor. Musíš pracovat přímo s bufferem a vedle si uložit délku.

    Přenos souboru udělej v cyklu. Načti 4KB do bufferu, zapamatuj si, kolik dat v bufferu skutečně je, a tyto dva parametry pak předej fwrite(). Buffer si alokuj staticky na pevnou velikost. Dynamická alokace paměti je pomalá (proto se používají alokátory, které si od jádra alokují velký blok najednou a ten pak rozdávají dál).

    Také ti to nebude fungovat s pojmenovanými rourami a soubory, do kterých se ještě stále zapisuje.
    Hello world ! Segmentation fault (core dumped)
    31.1.2014 08:38 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    OT:
    Dynamická alokace paměti je pomalá (proto se používají alokátory, které si od jádra alokují velký blok najednou a ten pak rozdávají dál).
    Jen pro zajímavost, díky jisté diskuzi zde, jsem si vytáhl staré zdrojáky a řekl jsem si že je upravím a něco zkusím (i když to nepotřebuji, ale vypadá to zajímavě nepotřebně, možná to pak hodím do blogu ;)), a při jedné úpravě mě opět překvapila, právě věc kolem toho co píšeš. Ve smyčkám rekurzivně jsem alokoval různě veliké bloky paměti (malé 8byte až ≈200B, v ø12-32byte)a to v řádu málo sekund i N-milionkrát, tak jsem si řekl, přesně to co píšeš, udělal jsem velmi jednoduchý alokátor. Ale i když provedl jen jednu alokaci celého bloku a nedělal nic jiného než testoval jestli má dost a posunoval counter (ukazatel), tak jsem byl na stejné rychlosti a při použití omp + critical dokonce na nižší, než při postupných alokacích, jediné co bylo rychlejší, tak free, ale spíš díky tomu, že při postupných alokacích jsem při free musel projít celý „strom“, kdežto že tady stačilo jen to free na celý blok.
    Tuto zkušenost mám už opakovaně (C/C++ malloc/new), pokud jsou ty bloky moc malé a jedou rychle za sebou, tak na OS i herní konzole je to často stejně rychlá a někdy dokonce rychlejší volba než alokátor, záleží na poměru výkonného kódu mezi vs. množství a velikosti jednotlivých alokací.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    Josef Kufner avatar 31.1.2014 10:55 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Hm, že by jsme se dočkali nějakých optimalizací? Moje zkušenost s tímhle je už pár let stará. Tehdy jsem dělal nějaký parser, co alokoval načtené stringy a přechod na alokátor z Gtk přinesl zrychlení v desítkách procent.
    Hello world ! Segmentation fault (core dumped)
    31.1.2014 21:06 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Příloha:
    Abych nešířil bludy, tak to raději ještě upřesním, vytáhl jsem si ze svn verzi s alokátorem (kde jsem to řešil) a chová se mi to tak jak jsem popsal i s různými druhy optimalizace.
    Tak jsem si udělal „nesmyslný“ kód viz příloha a na jednom PC (Core2Duo) mám při optimalizaci -O0(nebo-li -O nezadáno) verzi skupinu s „floating“ nepatrně nejrychlejší s malloc (tedy roj malých alokací) a na herní konzole (i7/W7/cygwin) v této sekci dokonce poměr 1:4 ve prospěch malloc. Ostatní optimalizace, jsou v neprospěch malloc, nicméně jsou někdy v sekci floating nepatrné. Na i7, ze které píšu mám sekci floating vs -O0 v zásadě všechny hodnoty stejné a u -O1 a -O3 mi neodpovídají rozdíly bez floating a s floating (ztráta výkonu oproti malloc je s floating o kus nižší).
    Takže bych řekl, že to nejsou optimalizace alokace, ale (ne)optimalizace kompilátoru a dost záleží na to co se děje mezi těmi alokacemi a alokátor je dobrý nápad, jen to nemusí přinést vždy to patřičné ovoce. Ale při použití valgrind budeš rozhodně šťastnější s alokátorem (bude to mnohem rychlejší).
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    31.1.2014 11:25 Logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    No tam byl ale ten problém v tý synchronizaci, ta je strašně drahá.

    Měls (asi? :-)) použít TLS a mít pro každej vlastní pool.
    31.1.2014 11:26 Logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    vypadlo: ..pro každej thread...
    31.1.2014 12:34 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Nebudu vysvětlovat důvody proč ne (ono už z principu pokud použiješ omp for, tak tak nějak nechceš mít kontrolu nad jednotlivými thready), ale nejde o to, jde o to, že alokace velkého bloku a kontrola „máš dost“ + posunutí ukazatele při každém požadavku vs. alokace po drobcích vyšla na stejno (alokátor se provolával vždy, ale jednou udělal jen malloc a druhém případě alokoval na začátku a pak dělal to výše uvedené).
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    1.2.2014 15:25 logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    1) První a základní optimalizace openMP programu je odstranění kritických sekcí. Dělat porovnávání různejch alokátorů, když tam mám odstranitelnou kritickou sekci je IMHO blbina.

    2) Optimalizovat multithread aplikace bez toho, aniž by ses chtěl zabejvat jednotlivejma threada je jak jezdit s autem, ale nechtít šahat na volant. Jo, taky někam dojedeš... U multithread aplikací je dosti klíčové, jak se chovají thready, jak si navzájem zneplatňujou cache, jak na sebe musej čekat atd...

    3) Použití TLS není žádná kontrola nad jednotlivými thready. Konkrétně v novym C++ 11 to znamená, že deklaruješ proměnou jako thread_local a to je vše. V gcc lze použít __thread. Je to na kód snad úspornější, než označování kritické sekce a vyžaduje to stejnou míru "starosti" o konkurenci threadů (tady v tý proměnný může dojít ke konfliktu, jak ji ochráním?) jen ji řešíš jiným (a daleko vhodnějším) způsobem.

    4) Nevim jaks testoval, ale muj rychlej test ukazuje, že vlastní alokátor je škálovatelnější a násobně rychlejší než malloc

    Muj alokátor, openmp (4thready, 2core + multithreading) 0.580s Muj alokátor singlethread 0.609s Malloc, openmp (4thready, 2core + multithreading) 10,867s Malloc singlethread 6.647s

    na dvanactijadru jsou vysledky podobný, malloc neškáluje a i v singlethread je násobně pomalejší, custom allokátor škáluje krásně

    kompilovano s
    gcc -fopenmp -O1 test.c -std=c99

    Kód
    
    #include "stdlib.h"
    
    void* alloc1(int bytes) {
         return malloc(bytes);
    }
    
    const int CHUNK_SIZE = 1024*1024;
    
    
    void* alloc2(int bytes) {
       static __thread void* alloc_start = 0;
       static __thread void* alloc_end = 0;
       static __thread void* alloc_ptr = 0;
    
    
       if(alloc_start + bytes > alloc_end) {
         void* new_buffer = malloc(CHUNK_SIZE);
         *(void**)new_buffer = alloc_start;           //previous allocated chunk
         *(int *)(new_buffer + sizeof(void*)) = 0;    //number of allocated substrings
         alloc_start = new_buffer;
         alloc_end = new_buffer + CHUNK_SIZE;
         alloc_ptr = alloc_start + sizeof(void*) + sizeof(int);
       }
       void *ret = alloc_ptr;
       alloc_ptr+=bytes;
       return ret;
    }
    
    int main(void) {
    #pragma omp parallel for
      for(int r=0;r<1024*1024*200;r++)
        alloc2(r % 21 * r % 13);
    }
    
    1.2.2014 16:04 logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    A ještě - teď jsem našel vedle v threadu Tvuj testovací kód, takže už vim, jaks testoval.... nebo spíš nevim. Zvětšil jsem počet iterací desektrát a i u float kódu mi Tvoje implementace malloc vyšla na 14.2s ku 12.5s u custom alokátoru, což je podstatnej rozdíl.

    - A to ten alokátor neni napsanej zcela efektivně (je rozumější alokované chunky držet ve spojáku s hlavou, takže k aktuálnímu bufferu je hned přístup: tím odpadne přístup do dvou oblastí paměti a jedna indirekce, indexovaný přístup do chunků paměti potřeba není).

    - Navíc float operace jsou dost drahý, tady se bavíme o zpracovávání textů, kde dobře napsanej stavovej automat nemusí bejt složitější než ta integer verze kódu.
    1.2.2014 16:54 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    Ten test byl jen následný - pro zajímavost, ne to, co jsme popisoval jako první, to je moc komplexní, na jednoduchou prezentaci.

    Implementace by mohla být krapet, lepší, ale zas tam chybí podstatná část, nalezení prvního volného bloku v jednotlivých chuncích, takto udělaný alokátor by hodně plýtval.

    Přečetl jsi si i část Core2Duo, a taky to, že rozdíly při jednotlivých alokacích neodpovídali v sekce bez floating a s. Není důležité co dělá vlastní kód samostatně, ale co dělá v součinnosti s ostaním.

    Nevytrhávej s kontextu, reagoval jsem na kontrétní větu, i s uvozením „OT“, kde jsem chtěl rozporovat obecnou informaci, že alokátor je vždy zásadním přínosem.

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    1.2.2014 18:54 logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Takto udělaný alokátor je připraven na usecase, kdy se např. zpracovává soubor a pak se celý dealokuje. Vcelku běžná praxe.

    Pokud chci alokovat z fragmentované paměti, pak je zas blbost psát vlastní alokátor, protože implementace malloc řeší přesně toto a určitě to bude řešit lépe, než za hodinu napsaný kód...
    1.2.2014 16:35 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    1. Znovu, pointa je v tom, že daná aplikace běží stejně rychle bez alokátoru, jak s alokátorem i bez omp. To že, s omp je/byla pomalejší s alokátorem který měl critical sekci je (asi) logické, ale zanést do aplikace jednotlivé alokátory pro jednotlivé thready by mělo nepříjemné side efecty se zbytky, takže by to nepřicházelo v úvahu. Celkem jistě by to pak nebylo pomalejší, nicméně obtížně implementovatelné a s nepříjemnými side efekty a pokud v aplikaci je i při milionech alokací (přes malloc) jejich vlastní čas zanedbatelný tak to stejně nic nepřinese.

    2. Tvůj názor, můj je, že omp použiji jednoduše (a téměř výhradně tehdy pokud thready na sebe čekat nemusí), pokud je to složitější, řídím si thready a rozdělování úloh detailně já.

    3. Nemám k tomu co říct.

    4. Udělej si třeba nesmyslný, ale lepší(komplexnější) test a měř celkově strávený čas algortimu, ne jen alokaci navíc nepoužité paměti - to snad ani testovat nelze (nemá význam).

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    1.2.2014 18:43 logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    1a) To, co jsi tvrdil, bylo, cituji:
    "Tuto zkušenost mám už opakovaně (C/C++ malloc/new), pokud jsou ty bloky moc malé a jedou rychle za sebou, tak na OS i herní konzole je to často stejně rychlá a někdy dokonce RYCHLEJŠÍ volba než alokátor,
    Samozřejmě může teď tvrdit, že když do vlastního alokátoru vrazíš sleep (něco podobnéhos defakto dělal, kdyžs to volal s O0), tak je určitě pomalejší, ale s odpuštěním když se porovnávají algoritmy, tak má smysl porovnávat pouze dobře napsané a stejně zoptimalizované algoritmy: a dobře napsaný custom alokátor je rychlejší než generický malloc. To můj test (a koneckonců i Tvůj) jasně prokázal. To, že když na každou alokaci přijde množství další práce Xkrát delší nežli trvá samotná alokace, tak je přínos v zrychlení alokace nevýrazný, je pravda, ale to je zaprve dosti jiné tvrzení než to, že malloc je rychlejší, jaks psal - a navíc tvrzení na úrovni věty "Kružnice je kulatá".

    V tom, že existují příklady, kdy opravdu vlastní alokátor význam nemá máš pravdu, ale sám Tvůj testovací (nefloating) kód, kde složitost nealokace odpovídá zpracování pomocí jednoduchého konečného automatu krásně ukazuje, že alokátor v případě, kdy je velká část programu složená z alokací, smysl rozhodně má. Totéž dokládá i Josef Kufner.

    A to jsou ty testy ještě navíc velmi příznivé pro malloc, protože se do těch alokací nemíchají alokace a dealokace jiných paměťových bloků, které zvětšují fragmentaci paměťového prostoru a zesložiťují mallocu vyhledávání volných bloků.

    1b) Jaké nepřijemné sideefekty? Že se nedá dealokovat z jiného threadu? Dá se to napsat i tak, že si data s sebou nesou tag. kterým, threadem byly alokovaný a tak je lze dealokovat z jiného threadu, častý usecase je, že dealokaci provedu najednou po skončení práce (když zpracovávám dokument) pro všechny stringy najednou atd.... Jaký konkrétně sideefekt máš na mysli?

    2) Tvůj názor Ti neberu, ale evidentně je s odpuštěním nepříliš užitečný, když evidentně Tě vede k tomu, že píšeš alokátor s omp critical, když lze totéž vyřešit Xkrát rychleji pomocí TLS. Právě genialita OpenMP je, že Ti nechávají volnost, co necháš vyřešit pomocí openMP automaticky a co budeš detailněji ladit (existují i direktivy omp parallel, které Ti nechávají větší volnost v tom, co thready dělají, existují funkce omp_get_thread_id atd...). Většinou je totiž problém skryt v nějakém detailu, který je snadno řeitelný vhodným SW návrhem a psát si kvůli tomu "vlastní OpenMP" je zbytečné. Nehledě na to, že za OpenMP je spousta práce a tak vlastní implementace bude zpravidla horší. 4) Tvrdil jsi:
    Ale i když provedl jen jednu alokaci celého bloku a nedělal nic jiného než testoval jestli někdo má dost a posunoval counter (ukazatel), tak jsem byl na stejné rychlosti a při použití omp + critical dokonce na nižší, než při postupných alokacích,
    což můj testovací kód jednoznačně vyvrací - pokud nedělám nic, tak je custom alokátor dvakrát rychlejší, u paralelní verze je rozdíl ještě mnohem větší. Teda spíš než vyvrací Tvé tvrzení, tak spíš ukazuje na to, žes měl ten alokátor blbě napsaný.

    Pokud se bavíme o samotné užitečnosti custom alokátorů. tak má samozřejmě jediné, co má smysl testovat, je testovat pouze samotnou alokaci. Protože každý usecase toho alokátoru bude různý a tak nemá smysl říkat: "todle je standardní zátěž". Jediné, co tedy má smysl je změřit čas potřebný na jednu alokaci - to, jestli zlepšení v řádu např. desítek mikrosekund na jednu alokaci má v konkrétním případě smysl si pak přeci člověk snadno zjistí.

    Naopak pokud změřím čas zašpiněný nějakym mikrosleepem, tak vlastně nevím nic: protože v reálném použití může být objem té další práce řádově menší i větší než ten microsleep.
    1.2.2014 20:39 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    Ad 1. side-efect, je využití víc paměti než je ve výsledku třeba, a s jednotlivými thready se tento prostor zvětšuje.

    Ad 2. Dělej si závěry jaké chceš, když si troufáš bez znalosti všech podmínek…, pokud budeš používat omp_get_thread_id apod. jistě víš, že to má také detail - režie.

    Ad 4.„nedělal nic jiného“ = alokátor nedělal nic jiného něž to popsané(popis funkce alokátoru), zbytek kódu aplikace intenzivně pracoval (ono alokátor, tak nějak sám o sobě není na nic :)).

    Pokud se bavíme o samotné užitečnosti custom alokátorů. tak má samozřejmě jediné, co má smysl testovat, je testovat pouze samotnou alokaci.
    Mám jiný názor, je sice dobré, že alokátor v holém testu vyleze super, ale hlavní je, jak se pak chová v součinnosti s celkem a na daném OS.

    PS: Piš to kratší… ;)

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    1.2.2014 22:51 logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    1) side effect není větší využití paměti, protože při rozumné distribuci práce mezi thredy bude paměťová náročnost threadů podobná a proto může mít každý thread odpovídajícně menší buffer. Při exponenciálním nárůstu velikostí alokovanejch chunků ani nemusí být původní pool příliš velkej a amortizovaná složitost příliš nestoupne, zatímco paměťová náročnost nebude asymptomálně větší než v jednothreadovém řešení. Navíc, zavrhnout desetkrát rychlejší řešení kvůli o něco větší spotřebě paměti - psal jsi sideefect, který brání v použití řešení...

    2a) no jsou dvě možnosti (nebavíš-li se o konkrétním případě): buďto závěry neříkáš vůbec (pak ale debata nemá smysl) nebo tzn. generalizuješ. Tam samozřejmě obvykle existují výjimky, ale ty nic nemění na platnosti pravidla.

    2b) Overhead get_thread_num je hodně malej, nicméně pro tendle případ ta fce potřeba není, takže je to trochu OT tvrzení. A i kdyby byl overhead velkej, co ti brání si výsledek té funkce zacachovat?

    4) Pokud Tě zajímá chování v konkrétním případě, pak ano. Pokud jde o princip, pak je vytváření umělých kontextů blbina, právě proto, že každý kontext je jiný. Zde se od začátku bavíme o principu.
    2.2.2014 00:17 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    1) Jak myslíš…, …aby měl alokátor smysl, je třeba alokovat po výrazně větších blocích a eliminovat počet fyzických alokací a pak v každém posledním alokovaném bloku zůstane relativně spousta nepoužité paměti a to je nežádoucí vedlejší efekt.

    2a) No jasně, že neříkám všechno, protože kdyby to bylo triviální, tak ti sem ten k prdnu abych to nemusel vysvětlovat.

    2b)Je malý, stejně jak může být malý zisk s využití alokátoru.

    4) Možná ty se bavíš o principu, já od začátku prezentuji to k čemu jsem nedávno dospěl v konkrétním případě a tím jsem vyvracel obecný předpodklad, že alokátor vždy znamená zvýšení rychlosti.

    Zjednodušeně, aby alokátor vždy znamenal přínos, museli bychom ignorovat, způsob fungování HV i OS, který nefunguje sériově, lineárně a bez vzájemných závislostí jednotlivých prvků, ano na Pentiu nebo 486 s adekvátním OS byl rozdíl až několika řádům s „předalokací“ a bez, ale ty rozdíly docela rychle mizí a možná za pár let se budou knihovní alokátory jen wraperry na malloc(low level alokaci) a třeba budeme mít k dispozici běžně terabajty paměti a budu moci konečně vyzkoušet některé nápady :), pišu tyto blafy taky proto, že mě to nebaví, já to tady vidím a nevadí mi to a ty voláš po jednoduché přesně dané jistotě.

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    3.2.2014 16:52 Logik
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    1a) Pokud je volání malloc p*pomalejší než volání custom alokátoru, pak celkový čas custom-alokátoru včetně vnitřní alokace, vyčerpávající celý chunk díky k alokacím je p + k. Pokud bych to řešil pomocí malloc, pak by byl čas p*k. Z toho plyne, že aby byla alokace pomocí custom alokátoru rychlejší, stačí, aby chunk byl velký alespoň p/(p-1) alokací. To je i pro vcelku zanedbatelný faktor 1.1 pouze 11 akolací. To jsme furt v řádu max jednoho kilobyte, tak kde je ta spousta nevyužité paměti?

    1b) Malloc nedělá žádnou fyzickou alokaci, tu dělá systémové volání o jednu úroveň níže než malloc. Malloc je úplně stejný alokátor, jako ten náš testovací, akorát řešící generický případ včetně fragmentaci paměti atd... Malloc fyzicky alokuje velké chunky paměti a dále je rozděluje.

    2b) Přidání volání omp_get_thread_num do testu nemá měřitelný vliv na rychlost vykonání kódu. Použití malloc místo custom alokátoru zpomalí můj testovací příklad na 12jádru více než desetkrát. Tomu říkáš stejně malý?

    4) V tom případě si vyvracel předpoklad, který tu nikdo neříkal a který je zcela evidentní. Ano, ztratit čas implementací rychlejšího algoritmu má smysl pouze v případech, kdy čas ztrávený tímto algoritmem tvoří podstatnou část běhu programu. To je snad jasné každému, ne?

    Navíc jsi neprezentoval jen jeden konkrétní případ, na závěr svého příspěvku jsi slovy
    "tuto zkušenost mám již opakovaně"
    generalizoval - sice ne explicitně, ale implicitně ano.

    5) Malloc je knihovní funkce a většina jejího kódu běží v userspace. Její rychlost na OS tedy příliš nezávisí: závisí především na kvalitě libc knihovny, která může být přes různé OS stejná: např. glibc není problém provozovat na unixu, linuxu i BSD. Tvoje tvrzení by tak bylo možná pravdivé u velkých alokací dělaných pomocí přímého mapování fyzické paměti (mmap), ale tady se bavíme o malých alokacích a tam je to s prominutím prostě nepravda, v tomto případě nejvíce času nespotřebuje OS a systémová volání, ale userspace knihovní kód.

    Už vůbec netuším, jak by se v rychlosti malloc projevil jiný procesor - co konkrétně na staré 486 šlo při mallocu (relativně k rychlosti CPU) pomalu a na haswellu jde rychle?

    Malloc funguje defakto úplně stejně, jako custom alokátor: naalokuje od jádra OS velký kus paměti a ten pak po kouskách přiděluje jednotlivým voláním malloc. To, co dělá malloc složitým jsou dvě věci a) řešení fragmentace paměti, vyhledávání volného bloku atd... , b) mezithreadová synchronizace (týká se některých implementací mallocu, některé todle řeší). Pokud můžeš ušetřit na jedné z těchto věcí, pak se Ti hodí si napsat vlastní alokátor.

    Tj. pro případ A - např. pokud hodně alokuješ a chceš všechno uvolnit najednou, a případ B - pokud hodně alokuješ v různejch threadech a neceš si alokovaný věci mezi threadama půjčovat. Právě proto jsou Tvoje námitky proti custom alokátoru nesmyslný: psát vlastní alokátor s omp critical jde právě proti tomu, co můžeš vlastním alokátorem ušetřit. Stejně jako výtka, že ten jednoduchý alokátor neřeší fragmentaci paměti - on ji totiž neřeší úmyslně právě proto, že je jednoduchý a kdyby ji řešil, tak nemá smysl ho psát, protože malloc už napsaný je.

    3.2.2014 20:54 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Hezky jsi to rozebral a nacpal jsi mě do role odpůrce custom alokátoru;
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 31.1.2014 15:47 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Pridal jsem si kontrolu pro fread a zjistil jsem, ze nenacte korektne soubor a nevim proc, klient mi na tomto spadne.

    Vzdycky mi to haze reading error:
    
    fd = fopen(path, "rb");
        if (!fd)
        {
            fprintf(stderr, "Unable to open file %s", path);
            return;
        }
    
        fseek(fd, 0, SEEK_END);
        fileLen=ftell(fd);
        rewind(fd);
        
        fbuffer=(char *)malloc(fileLen); 
        if (!fbuffer)
        {
            fprintf(stderr, "Memory error!");
            fclose(fd);
            return;
        }
        
        
        while(!feof(fp)) {
            fread(fbuffer, 1, 1, fp);
        printf("%02x\n",byte);
    }
        
        result = fread (buffer,1,fileLen,fd);
        if (result != fileLen) {
            fputs ("Reading error",stderr); 
            exit (3);
            
        }
    
    
    Soubor chci pote spojit s message pomoci memcpy (dle tve rady) takto:
    
    char end[1]; 
    end[0]= '\n';
    fclose(fd);  
        
        size_t len1 = strlen(message), len2 = strlen(fbuffer);
        char *concat = (char*) malloc(len1 + len2 + 2);
    
        memcpy(concat, buf, len1);
        memcpy(concat+len1, fbuffer, len2+1);
        memcpy(concat + strlen(concat), end, 1);
    
        send(sockfd, concat, strlen(concat), 0);
    
    
    Ale nevim jak docilit toho, aby se doubor nacetl korektne.

    Psal jsi o cyklu, tale to jsem pochopil, ze se to vztahuje az ke cteni prichoziho bufferu na serveru.
    31.1.2014 17:36 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Trochen jsem zmaten...
    Fbuffer=(char *)malloc(FILELEN);
    while(!feof(fP)) {
      fread(Fbuffer, 1, 1, fP);
      printf("%02x\n",byte);
    }
    
    result = fread(?buffer,1,FILELEN,fD);
    Podle fileLen alokuješ fbuffer, ale do toho čteš z jiného descriptoru, než jsi si zjišťoval velikost a pak čteš do buffer, který nevím kde alokuješ.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 31.1.2014 18:09 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    jj, mel jsem tam zmatky, taky jsemsi vsiml a uz jsem to nacita dobre.
    tomes.io avatar 1.2.2014 22:23 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Tak jsem trosku pohnul, akorat jsem se ted za sekl na dvou vecech:

    1) Po prijeti zpravy nezapise server korektne vetsi soubor. Male souboru o velikosti nekolika bytu ano. Velke soubory, napriklad zdrojaky zapise nekorektne. Dival jsem se na kod dlouho, hodle dlouho a proste nemuzu prijit na to, v cem to je. Bud je chyba na strane sestaveni zpravy (tedy klient) nebo ve zpusobu cteni z bufferu a zapisu do souboru na strane serveru. Za boha nemuzu prijit na to, v cem to je. Nejsem schopny to naprogramovat.

    Zde klientska fce ktera posila zpravy. Na zacatek da udaj o delce zpravy, pak zpravu a nakonec data (buffer se souborem):

    void send_msg(char *message, char *path) {
    
        char msg[1024];  
        strcpy(msg, message);
        FILE * fr;
        long lSize;
        char * buffer;
        size_t result;
        char *header;
    
        fr = fopen(path, "rb");
        if (fr == NULL) {
            fputs("File error", stderr);
            exit(1);
        }
        fseek(fr, 0, SEEK_END);
        lSize = ftell(fr);
        rewind(fr);
    
        buffer = (char*) malloc(sizeof (char)*lSize);
        if (buffer == NULL) {
            fputs("Memory error", stderr);
            exit(2);
        }
    
        result = fread(buffer, 1, lSize, fr);
        if (result != lSize) {
            fputs("Reading error", stderr);
            exit(3);
        }
    
        fclose(fr);
        size_t len1 = strlen(msg), len2 = strlen(buffer);
    
        /* delka zpravy */
        asprintf(&header, "%d^", (int) len1 + (int) len2);
        printf("header is: %s\n", header);
        size_t len3 = strlen(header);
        
        char *concat = (char*) malloc(len1 + len2 + len3+1);
        
        if (concat == NULL) {
            MY_KILL_ON_ERROR("Concat message\n");
            exit(1);
        }
      
        /* spoj vse dohromady */
        memcpy(concat, header, len3);
        memcpy(concat + len3 , msg, len1);
        memcpy(concat+ len3 +len1, buffer, len2);   
        send(sockfd, concat, strlen(concat), 0);
    
        free(buffer);
        free(message);
        free(header);
        message = NULL;
    }
    
    Tady jsou funkce serveru. thread_reader nacte buffer (zjisti si delku zpravy a souboru, nacte a posle do fce handle_msg ke zpracovani):
    
    void handle_msg(char *buf, int buflen, int hdrlen) {
        
        char *p_str;
        char chunk[50000];
        char home[1024];
        char path[1024];
        int j;
        int flag;
        int hm_len;
        int parlen;
        int is_dir;
        long fsize; /* delka souboru */
        int meslen;
        int f, ofset;
    
        /*zkopiruj buffer do chunk pro ucely parsovani pomoci strtok*/    
        if (buflen < 1024) {
                    memcpy(chunk, buf, buflen);
                    f = 0;
        } else {
            memcpy(chunk, buf, 1024);
            buflen -= 1024;
            ofset = 1024;
        }
    
        while (f) {
            if (buflen < 1024) {
                    memcpy(chunk + strlen(chunk), buf + ofset, buflen);
                    fsize = 0;
            } else {        
                memcpy(chunk + 1024, buf + ofset, 1024);
                buflen -= 1024;
                ofset += 1024;
            }
        }
        /* parsuj zpravu */
        j = 0;
        p_str = strtok(chunk+hdrlen, ":");
    
        while (p_str != NULL) {
    
            if (j == 0)
                flag = atoi(p_str);
            else if (j == 1)
                is_dir = atoi(p_str);
            else if (j == 2)
                hm_len = atoi(p_str);
            else if (j == 3)
                parlen = atoi(p_str);
            else if (j == 4)
                fsize = atol(p_str);
            else if (j == 5)
                strcpy(path, p_str);
    
            p_str = strtok(NULL, ":");
            j++;
        }
        /* kontrolni vypisy */
        printf("flag: %d\n", flag);
        printf("isdir: %d\n", is_dir);
        printf("hmlen: %d\n", hm_len);
        printf("parlen: %d\n", parlen);
        printf("fsize: %ld\n", fsize);
        printf("path: %s\n", path);
    
        /* nastav cestu do domovskeho adresare */
        memset(home, '\0', strlen (home));
        strcpy(home,mydir);
        strcat(home, path + hm_len);
        home[strlen(home)] = '\0';
    
        char *parent = NULL;
        parent = get_parentdir(home);
    
        if ((flag == IN_CREATE) || (flag == IN_MOVED_TO) || (flag == IN_CLOSE_WRITE)) {
            mkpath(parent, S_IRWXU | S_IRWXG | S_IRWXO);
            if (is_dir)
                mkpath(home, S_IRWXU | S_IRWXG | S_IRWXO);
            else {
                FILE *fr = fopen(home, "wb");
                if (fr == NULL)
                    printf("File Cannot be opened file on server.\n");
    
                /* vypocti delku bufferu pred daty */
                meslen = (buflen - fsize) + hdrlen;
    
               /* zapisuj do souboru postupne po 1KB*/
                if (fsize < 1024){
                    fwrite(buf + meslen, sizeof (char), fsize, fr); 
                    fsize = 0;             
                } else {               
                     fwrite(buf + meslen, sizeof (char), 1024, fr);
                     fsize -= 1024;
                     meslen += 1024;
                }                     
                while (fsize) {
                    if (fsize < 1024) {
                        for (j = 0; j < fsize; j++) {
                            fwrite(buf + meslen, sizeof (char), fsize, fr); 
                            meslen++;
                        }
                        fsize = 0;
                    } else {                   
                        fwrite(buf + meslen, sizeof (char), 1024, fr);
                        fsize -= 1024;
                        meslen += 1024;
                    }
                }           
                fclose(fr);
            }
        }
        free(parent);
    }
    
    
    Delal jsem vse podle vasich rad. Mam delku souboru, delku zpravy, zkopiruji prislusny pocet bajtu a poslu do fwrite. U malych souboru to funguje, u vetsich, treba kolem 10kB to nefunguje. Nevim proc a uz jsem z toho fakt zoufaly.

    2) toto vse "funguje" v netbens debuggeru. Male soubory zkopiruje, vetsi zkopiruje, ale obsah je rozhazena zmet znaku. Kdyz ale debugger vypnu a spustim to normalne (nebo z prikazove radky) tak se nejenze nezkopiruje soubor, ale kontrolni vypisy promennych (flag, delka message, path) maji vzdy nulovou hodnotu. absolutnen etusim proc, setkal se s tom nekdy nekdo?
    1.2.2014 22:47 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    Zběžným pohledem len2 = strlen(buffer) zjistí délku pro první '\0', takže binární filesi smůla jsou oříznuty (a mimochodem tu len2 už máš v result i lSize, jestli se dobře dívám).

    Na handle_msg nemám fčul náladu :(.

    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    tomes.io avatar 1.2.2014 23:05 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Jeste jsem nasel chybu v handle_msg pri zapisu do souboru. V cyklu WHILE se spatne zapisovalo do souboru, tak jsem to opravil:
    
    while (fsize) {
                    if (fsize < 1024) {
                        fwrite(buf + meslen, sizeof (char), fsize, fr); 
                        fsize = 0;
                    } else {                   
                        fwrite(buf + meslen, sizeof (char), 1024, fr);
                        fsize -= 1024;
                        meslen += 1024;
                    }
                }           
    
    
    Problem to ovsem neresi stejne. A nemuzu poradne debugovat, kdyz mi v debuggeru neco jede, ale naostro neprochazi nic :(

    Sangala: dik aspon za tohle, to by u tech binarnich filu delalo problem (zatim zkousim jen na textovych).
    tomes.io avatar 1.2.2014 23:25 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Mno tak jsem zjistil, kde je zakopany pes. Je to ve fci thread_writer (kterou jsem sem zapomnel vlozit, ehm.. uz je pozde, omlouvam se :), konkretne recv():
    
    void *thread_reader(void **_client) {
        
        client_t *client = *_client;
        char *buf = NULL;
        int meslen = 0;
        int len = 0;
        int i, j;
        char *rest;
        void *tmp;
        char *meschar;
        
        while (1) {
            
            if ((tmp = realloc(buf, len + 1024)) == NULL) {
                free(buf);
                buf = NULL;
                exit(1);
                
            } else
                buf = (char*) tmp;
    
            len += recv(client->fd, buf, 1024, 0);
            
            for (i = 0; i < len; i++) {
                /* zjisti delku zpravy */
                if (buf[i] == '^'){
                    meschar = (char*)malloc (i-1);
                    
                    for(j = 0; j < i; j++){
                        meschar[j] = buf[j];                  
                    }            
                    meslen = atoi(meschar);              
                    j++;                             
                }          
                if(i == (meslen + j))
                    break;                               
            }
    
            handle_msg(buf, meslen, j);
            rest = (char *) malloc(len - i);
            broadcast(client->id, buf, i + 1);
            free(buf);
            free(meschar);
            buf = rest;
        }
    }
    
    Problem je, ze bufer je vzdy pri vetsich souborech velky jen 1024 B. Takze posle prvnich 1024 do handle_msg a potom se provede dalsi loop a posle dalsich 1024....
    
    Takze ted premyslim, jak to vyresit. Ted vecer uz asi nic nevymyslim, ale uvitam jakoukoliv radu.
    
    
    tomes.io avatar 2.2.2014 00:09 tomes.io | skóre: 12 | blog: tomesh
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Jeste mi to nedalo a prozkoumal jsem ten recv(). Zvetsil jsem buffer:
    int buffsize = 1024*1024;
    setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
    
    Cela fce tady:
    void *thread_reader(void **_client) {
        
        client_t *client = *_client;  
        int meslen = 0;
        int len = 0;
        int i, j;
        char *meschar;
        int buffsize = 1024*1024;
        setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
        char *buf;
        
        while (1) {
            buf = (char *) malloc(buffsize);
    
            if (buf == NULL) {
                free(buf);
                buf = NULL;
                exit(1);
            } 
            len += recv(client->fd, buf, buffsize, 0);
            
            for (i = 0; i < len; i++) {
                /* zjisti delku zpravy */
                if (buf[i] == '^'){
                    meschar = (char*)malloc (i-1);
                    
                    for(j = 0; j < i; j++){
                        meschar[j] = buf[j];                  
                    }            
                    meslen = atoi(meschar);              
                    j++;                             
                }          
                if(i == (meslen + j))
                    break;                               
            }
            handle_msg(buf, meslen, j);
            broadcast(client->id, buf, i + 1);
            free(meschar);
            free(buf);
        }
    }
    
    A uz mi vetsi soubory prochazi, ale opet jen pri debugovani, kdyz si jedu v debuggeru krok za krokem. To mi vse krasne vypisuje, vsechny flagy:
    flag: 8
    isdir: 0
    hmlen: 30
    parlen: 30
    fsize: 1655
    path: /home/tomesh/Dropbox/C/dropbox/test
    home: /home/tomesh/Dropbox/C/sync/test
    
    Jenze v ostrem rezimu (v netbeans nebo v prikazove radce) mi to vubec neprochazi:
    flag: 0
    isdir: 0
    hmlen: 0
    parlen: 0
    fsize: 0
    path: 
    home: ./srv
    
    Nevite nekdo cim by to mohlo byt?
    2.2.2014 11:23 potato
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Megabajtový buffer je trochu exces... Každopádně ten for-cyklus dělá cokoli, meschar se může alokovat opakovaně, či vůbec nealokovat, nedává mi smysl pokračovat v procházení, když už jsi něco našel, meschar každopádně nikdy nemá uzavírací \0, takže atoi() může udělat cokoli. Když chceš použít memchr(), použij memchr(), nepiš for-cykly.
    Josef Kufner avatar 2.2.2014 18:28 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Někde, kdysi dávno, jsem viděl benchmark různých velikostí bufferu při kopírování souboru. Od 4KB bufferu výš už výkon prakticky nerostl. A 4KB jsou velikost je velikost jedné stránky v paměti, takže pokud není nějaký další důvod, je optimální velikost právě 4KB. Některé více či méně exotické systémy mohou mít stránku jinak velkou, takže je vhodné na to při portování aplikace myslet, případně vyhrabat nějakou vhodnou konstantu.
    Hello world ! Segmentation fault (core dumped)
    3.2.2014 08:46 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Mě přijde, že už to dnes je putna, pokud je buffer aspoň 4K (tedy v souladu s tím co píšeš), ale dřív jsem hodně získával na Win(9X/NT) s 32KiB buferem, oproti většímu a oproti menšímu byl výrazný rozdíl (hlavně na W9X, na NT měl podobné chování i bufer 64KiB), na Win9X s FATkou to mohl být i řádový rozdíl (asi to bylo dáno velikostí bloku). Fčul často čtu i několik setmega-až giga na jeden fread je to snazší (aby nedošlo k mýlce, tak za předpokladu, že ta data chci tak jak byla v souboru a neprochází transformací). Těch pár testů co jsem k vůli tomu dělal, už dnes nevykazují praktické rozdíly (a na SSD disku už sypou spíše chaotické výsledky, protože to je ovlivněno asi i táním ledovců :)).
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    3.2.2014 09:10 potato
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Proč používáš fread(), když data nijak netransformuješ? Standardní postup je soubor mmap()nout.
    3.2.2014 11:12 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Obvykle dva důvody:
    • Při multiplatformím řešení to není jen o jednom příkaze.
    • „Netransformuji“ nebylo přesné, například vyměním konce řádků za '\0', nebo vyměním index za pointer apod., takže změna jo, ale nemající vliv na paměťovou strukturu.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    3.2.2014 20:13 potato
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Multiplatformnost sice znamená někdy omezení na určitou podmnožinu funkcionality dostupnou všude, rozdíly mezi platformami ale řeší wrappery jako GMappedFile, boost::iostreams::mapped_file, QFile::map a pod. Je-li něco k disposici na všech příčetných platformách, kterými jsem coby programátor ochoten brát v úvahu, tak se tomu nemá smysl vyhýbat.
    3.2.2014 20:41 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?
    Netvrdím, že se vyhýbám mapování souboru i je fajn když si můžeš/chceš použít knihovnu jakou chceš. Ale tahat do závislostmi nenáročné aplikace/utility závislosti/licence uvedeného typu udělám (a QT asi jen tak neudělám :)), jen pokud to je nutné a přínosné, ne jen kvůli namapování souboru, když poslouží stejně dobře fread.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    Jardík avatar 4.2.2014 02:01 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: C - lze poslat soubor i zpravu na server soucasne?

    Z toho, co jsem letmo přečetl z tvých zdrojáků: sizeof operátor vrací hodnotu type size_t. V C nemusíš přetypovávat z void* na ukazatel jiného typu, pouze v C++. Argument pro malloc je typu size_t, né int. Funkce recv vrací ssize_t, asi z nějakého důvodu (viz. man 2 recv). sizeof(char) je vždy 1, nezávisle na tom, jestli má 8 nebo 125 bitů. Toto je potřeba vědět, než se posuneš dál.

    Dále je potřeba vědět, že funkce typu recv, read, send, ... nemusí přečíst/zapsat tolik bajtů, kolik po nich chceš. Ta hodnota určuje maximální počet bajtů, které zapíšou/přečtou. Kolik přečetly, ti řekne návratová hodnota. Může se ti vrátit i záporné číslo, např. když dojde k přerušení, když je plný buffer socketu, když nastane chyba, ...

    Celý tvůj cyklus mi přijde jako kravina:
    while (1) {
            buf = (char *) malloc(buffsize);
    
            if (buf == NULL) {
                free(buf); // zbytečný, ale ok, free se s NULL vyrovná, spíše to ale říká, že nevíš, o co jde.
                buf = NULL; // opravdu? proč, když už víš, že tam NULL je
                exit(1);
            } 
            len += recv(client->fd, buf, buffsize, 0); // A co záporné číslo??
            
            for (i = 0; i < len; i++) { // opravdu?? A to jako, že ty bajty z recv vždy zapisuješ na začátek bufferu (a né na nějaký předchozí offset), prakticky čteš z bufferu kraviny, cos tam nikdy nezapsal.
                /* zjisti delku zpravy */
                if (buf[i] == '^'){
            // ... atd další věci, co už jsem líný komentovat, třeba že atoi předpokládá nulou ukončený řetězec
        }
    

    Co ty potřebuješ, je ten protokol. Z toho, co jsem přečetl ze zdrojáku to vypadá, že tvůj protokol je něco jako:

    VELIKOST_ZPRÁVY, číslo v ascii, ukončené znakem '^'
    ZPRÁVA
    
    Z tvého kódu soudím, že chceš mít celou zprávu načtenou v paměti, měl bys si tedy zvolit nějaké omezení velikosti zprávy. Pokud nepotřebuješ, můžeš si zvolit nějaký buffer, třeba ho i alokovat na zásobníku, a postupně ho zapisovat do souboru, jak načítáš data.

    Dneska už jdu spát, jestli si pořád nebudeš vědět rady, více třeba zítra. Jsem ochotný ti napsat i kód, protože stejně nemám co dělat, všetně komentářů a vysvětlivek.

    Věřím v jednoho Boha.

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.