abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
eParkomat, startup z ČR, postoupil mezi finalisty evropského akcelerátoru ChallengeUp!
Robot na pivo mu otevřel dveře k opravdovému byznysu
Internet věcí: Propojený svět? Už se to blíží...
včera 22:44 | Komunita

Joinup informuje, že Mnichov používá open source groupware Kolab. V srpnu byl dokončen dvouletý přechod na toto řešení. V provozu je asi 60 000 poštovních schránek. Nejenom Kolabu se věnoval Georg Greve ve své přednášce Open Source: the future for the European institutions (SlideShare) na konferenci DIGITEC 2016, jež proběhla v úterý 29. listopadu v Bruselu. Videozáznam přednášek z hlavního sálu je ke zhlédnutí na Livestreamu.

Ladislav Hagara | Komentářů: 1
včera 15:30 | Zajímavý projekt

Společnost Jolla oznámila v příspěvku Case study: Sailfish Watch na svém blogu, že naportovala Sailfish OS na chytré hodinky. Využila a inspirovala se otevřeným operačním systémem pro chytré hodinky AsteroidOS. Použita je knihovna libhybris. Ukázka ovládání hodinek na YouTube.

Ladislav Hagara | Komentářů: 5
včera 14:15 | Nová verze

Byla vydána verze 7.1.0 skriptovacího jazyka PHP používaného zejména k vývoji dynamických webových stránek. Jedná se o první stabilní verzi nejnovější větvě 7.1. Přehled novinek v dokumentaci. Podrobnosti v ChangeLogu. K dispozici je také příručka pro přechod z PHP 7.0.x na PHP 7.1.x.

Ladislav Hagara | Komentářů: 0
včera 12:55 | Nová verze

Google Chrome 55 byl prohlášen za stabilní. Nejnovější stabilní verze 55.0.2883.75 tohoto webového prohlížeče přináší řadu oprav a vylepšení (YouTube). Opraveno bylo také 36 bezpečnostních chyb. Mariusz Mlynski si například vydělal 22 500 dolarů za 3 nahlášené chyby (Universal XSS in Blink).

Ladislav Hagara | Komentářů: 4
včera 11:55 | Pozvánky

Máte rádi svobodný software a hardware nebo se o nich chcete něco dozvědět? Přijďte na 135. sraz spolku OpenAlt, který se bude konat ve čtvrtek 8. prosince od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Sraz bude tentokrát tématický. Bude retro! K vidění budou přístroje jako Psion 5mx nebo Palm Z22. Ze svobodného hardwaru pak Openmoko nebo čtečka WikiReader. Přijďte se i vy pochlubit svými legendami, nebo alespoň na pivo. Moderní hardware má vstup samozřejmě také povolen.

xkucf03 | Komentářů: 0
včera 00:10 | Nová verze

Byla vydána verze 3.2 svobodného systému pro detekci a prevenci průniků a monitorování bezpečnosti počítačových sítí Suricata. Z novinek lze zmínit například podporu protokolů DNP3 a CIP/ENIP, vylepšenou podporu TLS a samozřejmě také aktualizovanou dokumentaci.

Ladislav Hagara | Komentářů: 0
1.12. 21:00 | Nová verze

Byla vydána beta verze Linux Mintu 18.1 s kódovým jménem Serena. Na blogu Linux Mintu jsou hned dvě oznámení. První o vydání Linux Mintu s prostředím MATE a druhé o vydání Linux Mintu s prostředím Cinnamon. Stejným způsobem jsou rozděleny také poznámky k vydání (MATE, Cinnamon) a přehled novinek s náhledy (MATE, Cinnamon). Linux Mint 18.1 bude podporován až do roku 2021.

Ladislav Hagara | Komentářů: 0
1.12. 16:42 | Nová verze

Byl vydán Devuan Jessie 1.0 Beta 2. Jedná se o druhou beta verzi forku Debianu bez systemd představeného v listopadu 2014 (zprávička). První beta verze byla vydána v dubnu letošního roku (zprávička). Jedna z posledních přednášek věnovaných Devuanu proběhla v listopadu na konferenci FSCONS 2016 (YouTube, pdf).

Ladislav Hagara | Komentářů: 0
1.12. 15:16 | Komunita

Na GOG.com začal zimní výprodej. Řada zlevněných her běží oficiálně také na Linuxu. Hru Neverwinter Nights Diamond lze dva dny získat zdarma. Hra dle stránek GOG.com na Linuxu neběží. Pomocí návodu ji lze ale rozběhnout také na Linuxu [Gaming On Linux].

Ladislav Hagara | Komentářů: 1
1.12. 13:14 | Bezpečnostní upozornění

Byla vydána verze 2.7.1 živé linuxové distribuce Tails (The Amnesic Incognito Live System), jež klade důraz na ochranu soukromí uživatelů a anonymitu. Řešeno je několik bezpečnostních problémů. Aktualizován byl především Tor Browser na verzi 6.0.7. Tor Browser je postaven na Firefoxu ESR (Extended Support Release) a právě ve Firefoxu byla nalezena a opravena vážná bezpečnostní chyba MFSA 2016-92 (CVE-2016-9079, Firefox SVG Animation

… více »
Ladislav Hagara | Komentářů: 0
Kolik máte dat ve svém domovském adresáři na svém primárním osobním počítači?
 (32%)
 (24%)
 (29%)
 (7%)
 (5%)
 (3%)
Celkem 759 hlasů
 Komentářů: 50, poslední 29.11. 15:50
Rozcestník
Reklama

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: 799×
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: 66
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: 66
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: 48
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: 66
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: 66
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: 66
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: 66
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.