Avatar billede jnusa Nybegynder
01. december 2004 - 09:51 Der er 18 kommentarer og
2 løsninger

Socket Programmering

Jeg er i gang med at lave en Proxy Server, og er ved at være færdig grundopbygningen (send/modtag, læs/rediger headerfields ect). Serveren virker efter henseende, men jeg kan ikke overføre Content-Type: image/jpeg, gif ect. Når jeg læser body content, fra disse pakker, læser jeg alt data, men i min buffer ligger der kun 4 bytes?! Det er meget mystisk. Jeg bruger den samme funktion til alt body content reads. (Bruger Mepis 2004, 2.6.7

Funktionen (read_body) får 3 parametre:
- int fd, filedescriptor til serveren hvor dataene skal læses fra. Jeg har læst en gang fra denne, da jeg på dette tidspunkt har hentet headeren.
- char *ptr, pointer til en dynamisk allokeret buffer, på størrelsen lig Content-Length i headeren. Dvs. størrelsen på dataene der ligger i body.
- int length, størrelsen på body, læst fra headeren.

funktion:
[CODE]
int read_body(int fd, char *ptr, int length)
{   
   
    int    res = 0;
    int total = 0;
   
    if(ptr != NULL)
    {    //errno = 0;
        while(total < length )
        {   
           
            if((res = (read(fd, ptr + total, length))) < 0)
                errexit("\nError readback from server. Error: %s", strerror(errno));
            if(res >= 0)
                total += res;
            printf("\n Read: %d\tTotal read: %d\t Total length: %d\tfd: %d", res, total, length, fd);       
            if(res == 0)
            {    puts("\nBREAK 0!!!!");
                break;
            }
            if(res < 0)
            {    puts("\nBREAK -1!!!");
                break;
            }
       
        }
        logit(ptr, "temp.log");
        printf("\nRecieved:\n%s", ptr);
    }
    else
        logit("\nEvt. malloc error -> no error handeling!", "system.log");   
   
    printf("\nSo far, so good!");
    return res;
}




Udprint fra terminal
[CODE]
HTTP version: 1.1
Status-code: 200
length: 138239
strlen(obj->body_content): 138239
Read: 66984    Total read: 66984        Total length: 138239  fd: 5
Read: 1448    Total read: 68432        Total length: 138239  fd: 5
Read: 1448    Total read: 69880        Total length: 138239  fd: 5
Read: 1448    Total read: 71328        Total length: 138239  fd: 5
Read: 1448    Total read: 72776        Total length: 138239  fd: 5
Read: 1448    Total read: 74224        Total length: 138239  fd: 5
Read: 1448    Total read: 75672        Total length: 138239  fd: 5
Read: 1448    Total read: 77120        Total length: 138239  fd: 5
Read: 1448    Total read: 78568        Total length: 138239  fd: 5
Read: 1448    Total read: 80016        Total length: 138239  fd: 5
Read: 1448    Total read: 81464        Total length: 138239  fd: 5
Read: 1448    Total read: 82912        Total length: 138239  fd: 5
Read: 1448    Total read: 84360        Total length: 138239  fd: 5
Read: 1448    Total read: 85808        Total length: 138239  fd: 5
Read: 1448    Total read: 87256        Total length: 138239  fd: 5
Read: 1448    Total read: 88704        Total length: 138239  fd: 5
Read: 1448    Total read: 90152        Total length: 138239  fd: 5
Read: 1448    Total read: 91600        Total length: 138239  fd: 5
Read: 1448    Total read: 93048        Total length: 138239  fd: 5
Read: 1448    Total read: 94496        Total length: 138239  fd: 5
Read: 1448    Total read: 95944        Total length: 138239  fd: 5
Read: 1448    Total read: 97392        Total length: 138239  fd: 5
Read: 1448    Total read: 98840        Total length: 138239  fd: 5
Read: 1448    Total read: 100288      Total length: 138239  fd: 5
Read: 1448    Total read: 101736      Total length: 138239  fd: 5
Read: 1448    Total read: 103184      Total length: 138239  fd: 5
Read: 1448    Total read: 104632      Total length: 138239  fd: 5
Read: 1448    Total read: 106080      Total length: 138239  fd: 5
Read: 1448    Total read: 107528      Total length: 138239  fd: 5
Read: 1448    Total read: 108976      Total length: 138239  fd: 5
Read: 1448    Total read: 110424      Total length: 138239  fd: 5
Read: 1448    Total read: 111872      Total length: 138239  fd: 5
Read: 1448    Total read: 113320      Total length: 138239  fd: 5
Read: 1448    Total read: 114768      Total length: 138239  fd: 5
Read: 1448    Total read: 116216      Total length: 138239  fd: 5
Read: 1448    Total read: 117664      Total length: 138239  fd: 5
Read: 1448    Total read: 119112      Total length: 138239  fd: 5
Read: 1448    Total read: 120560      Total length: 138239  fd: 5
Read: 1448    Total read: 122008      Total length: 138239  fd: 5
Read: 1448    Total read: 123456      Total length: 138239  fd: 5
Read: 1448    Total read: 124904      Total length: 138239  fd: 5
Read: 1448    Total read: 126352      Total length: 138239  fd: 5
Read: 1448    Total read: 127800      Total length: 138239  fd: 5
Read: 1448    Total read: 129248      Total length: 138239  fd: 5
Read: 1448    Total read: 130696      Total length: 138239  fd: 5
Read: 1448    Total read: 132144      Total length: 138239  fd: 5
Read: 1448    Total read: 133592      Total length: 138239  fd: 5
Read: 1448    Total read: 135040      Total length: 138239  fd: 5
Read: 1448    Total read: 136488      Total length: 138239  fd: 5
Read: 1751    Total read: 138239      Total length: 138239  fd: 5
Recieved:
ÿØÿà
So far, so good!
[/CODE]

Som man kan se, bliver der rent faktisk læst noget, men jeg får praktisk talt intet i min buffer (ud over de 4 bytes). Nogen der har nogle forslag til hvad  jeg kan gøre. Bar brugt 1½ uge på det nu, uden mærkbart resultat. Jeg undskylder for den lange terminal udskrift, men det var for at se, at read() functionen rent faktisk læser alt data. Håber nogen kan hjælpe.

/Jnusa
Avatar billede brilleaben Nybegynder
01. december 2004 - 10:40 #1
if((res = (read(fd, ptr + total, length))) < 0)
                errexit("\nError readback from server. Error: %s", strerror(errno));
            if(res >= 0) {
                total += res;
                length -= res;
            }

            .. osv ...
Avatar billede jnusa Nybegynder
01. december 2004 - 10:51 #2
Ja, det er en god optimerings reminder. Men stadigvæk ikke en løsning på mit problem. Jeg får stadigvæk ikke dataene ned, fra billederne... det eneste der ligger i bufferen er GIF89a#_  ikke andet (i tilfælde af jeg henter en gif billede). Andre der har nogle forslag
Avatar billede brilleaben Nybegynder
01. december 2004 - 11:00 #3
Det slog mig lige:

      logit(ptr, "temp.log");
        printf("\nRecieved:\n%s", ptr);


printf terminerer ved 0x00 - dvs, det du ser er 'G''I''F''8''9''a''#''_'0x00 + en
hel masse andet.  Istedet for at bruge printf så bruge "write" til at høvle det
ud med:

fd=open("output", O_RDWR);
write(fd, ptr, total);
close(fd);

... og brug så en hexviewer til at kigge data igennem med ...

Endvidere (optimering):

if (res>0) {
    total+=res;
    length-=res;
}

...
Avatar billede jnusa Nybegynder
01. december 2004 - 11:52 #4
Hmm... Mja, det er rigtigt at printf terminere ved 0x00, men min fil, som jeg logger alt til via logit(), burde være længere end 4 bytes. Jeg har prøvet at outmarke printf'n, kun logge indholdet af ptr, men samme reultat. I hex editoren er der FF D8 FF E0, som faktisk er de første 4 bytes i det billede jeg prøver at få fat på. http://www.leog.net/P1_logo.jpg
Jeg forstår ikke helt din write metode. Hvor/hvad skriver den til? En fil eller til terminalen? Eller er det ligemeget, da loggen ser ud som den gør?

[CODE]
int logit(char *buf, char *fname)
{
    FILE *fp;
    if((fp = fopen(fname, "a+")) < 0)
        puts("\n###logfejl");
    fputs(buf, fp);
    fclose(fp);
    return 0;   
}
[/CODE]
Avatar billede jnusa Nybegynder
01. december 2004 - 11:53 #5
Ov, det link til billedet, er ikke det samme billede, brugt til terminal udskriften :-)
Avatar billede brilleaben Nybegynder
01. december 2004 - 12:01 #6
Det med linket er da lidt af problemet.

Men stadig ... fputs/puts terminerer også på 0x00.  Alle I/O kommandoer der
ikke specificeres med en længde terminerer ved 0x00 (eller, i få kalds tilfælde
ved '\n').

Jeg ville nok have en ekstra 'logit' funktion:

[CODE]
int logitbin(char *buf, int len, char *fname)
{
    int fd;

    if ((fd=open(fname, O_RDWR))>-1) {
        write(fd, buf, len);
        close(fd);
    }

    return (fd >=0 ? 0 : -1);
}
[/CODE]

... og så bruge den til at skrive dine hentede data ud med.


.
Avatar billede brilleaben Nybegynder
01. december 2004 - 12:02 #7
Skal iøvrigt være:

fd=open(fname, O_RDWR|O_CREAT)


:-)
Avatar billede jnusa Nybegynder
01. december 2004 - 12:44 #8
Oka prøver jeg. Ang linket, var det blot for at pointere, at terminal udskriften fra post #1 var på en langt større fil end P1_logo.jpg (ca. 2876b). Ikke andet.
Det lyder dog, som om dette godt kunne være problemet. Det kræver dig at functionen send() og terminere ved 0x00. Jeg sender jo ptr bufferen videre til klienten via send.
Avatar billede brilleaben Nybegynder
01. december 2004 - 13:26 #9
send/recv terminerer ikke ved 0x00 - de terminerer når der ikke er mere at sende hhv. modtage.

Du, som afsender, bestemmer hvor meget der skal sendes:  send(fd, ptr, total, _flags_);

Som modtager bliver du nødt til at skalere din modtagerbuffer så den kan indeholde de data der skal modtages.  Dette kan bl.a. gøres med MSG_PEEK flaget til recv ...

... men det er en helt anden snak :-)
Avatar billede jnusa Nybegynder
01. december 2004 - 14:50 #10
Ok, prøvede at lave logitbin og bruge den i stedet. Jeg laver en memset på ptr bufferen inden jeg sender den til read_body. Resultatet er det samme. Den læser hele billedet, men gemmer GIF89ax  resten af bufferen indeholder 0 (fra memset). Andre forslag?
Avatar billede jnusa Nybegynder
01. december 2004 - 14:56 #11
Hmm... skulle mene at jeg skalere min buffer alt efter hvor meget data der er. Jeg kender jo størrelsen fra headeren. Dvs. hvis Content-Length er 2900b, så allokere jeg 2900b. Så det skulle ikke være noget problem. Syntes sku det er mærkeligt... har haft nogle threads på linuxquestions.org, og der var heller ikke nogen, der umiddelbart havde set det før.
Det virker jo perfekt med text, så jeg forstår det ikke helt.
Avatar billede brilleaben Nybegynder
01. december 2004 - 15:04 #12
Ku' du ikke prøve at lave et gennemløb ala:

[CODE]
HTTP version: 1.1
Status-code: 200
length: 138239
strlen(obj->body_content): 138239
Read: 66984    Total read: 66984        Total length: 138239  fd: 5
Read: 1448    Total read: 68432        Total length: 138239  fd: 5
Read: 1448    Total read: 69880        Total length: 138239  fd: 5
Read: 1448    Total read: 71328        Total length: 138239  fd: 5
Read: 1448    Total read: 72776        Total length: 138239 


... men med de rigtige værdier?

Hvorfor får du en GIF89ax når billedet er et jpeg???

Hvordan ser resten af din kode ud?  Umiddelbart burde read_body virke (ligner
til forveksling dem jeg selv bruger :-)
Avatar billede brilleaben Nybegynder
01. december 2004 - 15:05 #13
Prøv at memset med '\x01', kør dit program.  Er bufferen fyldt med GIF89ax og 0x01'er?
Avatar billede jnusa Nybegynder
01. december 2004 - 15:51 #14
Undskylder for at jeg ikke har være mere konsekvent mht. billede typen.. Hopper lidt frem og tilbage mellem jpeg og gif. Bruger http://www.leog.net/images/leog.gif frem over som reference fil.
(Virker tags ikke her? e.g. [CODE]?. Du skal nok få nogle points, men eksperten er ikke lige så vild med mozilla/firefox :) )

Min memset ser ud til at være overskrevet efter jeg har læst billedet. Den indeholder ikke 0x01, som jeg sat den til, men 0x00. Se prntscr: http://www.hootmail.dk/jnusa/term01.jpg
Så den skriver rent faktisk i ptr.

Terminal udskrift

HTTP version: 1.1      Status-code: 200
length: 2862
strlen(obj->body_content) efter read_body: 2862
Read: 2862    Total read: 2862        Total length: 2862    fd: 5
So far, so good!
Header + Body reply size: 3170

Jah, hvordan ser resten af min kode ud... jah. Der er jo ret meget af den. Her er lidt af det.

Har en funktion, read_reply(), som læser headeren, read_header(), og content, read_body. Desuden har jeg en struct som ser ud som flg:

------------------------------------------------------------------------
typedef struct {
    char * hdr[MAX_HEADERS];
    int lines;
   
    int where_content_type, where_content_length, where_chunked;
    int where_content_encoding, where_etag;

    //If headers contain request from client, status is always -1.
    int status;
    char *body_content;
    int body_length;
    char *method, *url, *proto, *host, *path, *bd, *transfer_encoding;
    int port, content_length, flags, image;
    int version;
    int chunklen;   
} http_headers;

------------------------------------------------------------------------

int read_reply(int fd, http_headers **obj)
{   

    int res=0;
    read_header(fd, obj);
   
    /**Store Key headersfields*/
    (*obj)->version = get_http_version(obj);
    (*obj)->status = get_status_code(obj);
    if(is_chunked(obj) == 1)
    {    puts("\nTransfer-Encoding: chunked");
        (*obj)->status = -2;
    }
   
    printf("\nHTTP version: 1.%d\tStatus-code: %d", (*obj)->version, (*obj)->status);
   
    if(((*obj)->status / 100) == 2)
    {
        (*obj)->body_length = get_length(obj);
        printf("\nlength: %d", get_length(obj));
        if((*obj)->body_length != -1)
        {
            (*obj)->body_content = malloc((*obj)->body_length+1);
            *((*obj)->body_content + (*obj)->body_length) = '\0';
            memset((*obj)->body_content, 0x01, (*obj)->body_length);
            logitbin((*obj)->body_content, (*obj)->body_length, "temp2.log");
            printf("\nstrlen(obj->body_content) efter read_body: %d", strlen((*obj)->body_content));
            read_body(fd, (*obj)->body_content, (*obj)->body_length);
        }
        else logit("\n\nCHUNKED", "content.log");
    }
    return 0;
}


------------------------------------------------------------------------
int read_header(int fd, http_headers **obj)
{
    int i = 0;
    int res = 0;
    char tempbuf[200];
    int size = 1;
    int temp = 0;
    int total = 0;

   
    while(i < 50 && size >0)
    {   
        size = read_line(fd, (char *)tempbuf);
        res += size;
        if( strcmp("\r", tempbuf))
        if (((*obj)->hdr[i] = malloc(res+1)) == NULL)
            puts("\nMalloc fejl - read_header");
        (*obj)->hdr[i][res+1] = '\0';
        strcpy((*obj)->hdr[i], (char *)tempbuf);
        if((*obj)->status != -1)
        {
            logit("\n", "reply.log");
            logit((*obj)->hdr[i], "reply.log");
        }
        else
        {
            logit("\n", "request.log");
            logit((*obj)->hdr[i], "request.log");
        }
        i++;
    }
    (*obj)->lines = i-1; //compensate for post addition
   

    return res;
}
------------------------------------------------------------------------
int read_body(int fd, char *ptr, int length)
{   
   
    int    res = 0;
    int total = 0;
    int readsize = length;   
   
    if(ptr != NULL)
    {    //errno = 0;
        while(total < length )
        {   
           
            if((res = (read(fd, ptr + total, readsize))) < 0)
                errexit("\nError readback from server. Error: %s", strerror(errno));
            if(res > 0)
            {
                total += res;
                readsize -= res;
            }
            printf("\n Read: %d\tTotal read: %d\t Total length: %d\tfd: %d", res, total, length, fd);       
            if(res == 0)
            {    puts("\nBREAK 0!!!!");
                break;
            }
            if(res < 0)
            {    puts("\nBREAK -1!!!");
                break;
            }
        }
       
        if (logitbin(strdup(ptr), length, "temp.log") < 0)
            puts("\nlogitbin fejl");
    }
    else
        logit("\nEvt. malloc error -> no error handeling!", "system.log");   
   
    printf("\nSo far, so good!");
    return res;
}
------------------------------------------------------------------------
Avatar billede brilleaben Nybegynder
01. december 2004 - 16:30 #15
Der er noget her der ikke stemmer ...  Du bruger strdup(ptr) i logitbin - strdup terminerer
også ved (0x00) - dvs. du burde får  string+0x00+garbage op til length bytes.

Kan du ikke uploade din kode så jeg kan hente den?

(Firefox virker da findt på eksperten .. :-)


NOTE
----

Taget fra read_reply (se kommentarer i koden ...

if(((*obj)->status / 100) == 2)
    {
        (*obj)->body_length = get_length(obj);
        printf("\nlength: %d", get_length(obj));
        if((*obj)->body_length != -1)
        {
            (*obj)->body_content = malloc((*obj)->body_length+1);
            *((*obj)->body_content + (*obj)->body_length) = '\0';
            memset((*obj)->body_content, 0x01, (*obj)->body_length);
            /*
            ** Denne logger udelukkende 0x01'er
            */
            logitbin((*obj)->body_content, (*obj)->body_length, "temp2.log");
            /*
            ** strlen er forkert at bruge eftersom du læser binære data
            ** Desuden kan du ikke udtale dig om body_content før _efter_  read_body
            ** (byt rundt på de to linjer :-)
            */
            printf("\nstrlen(obj->body_content) efter read_body: %d", strlen((*obj)->body_content));
            read_body(fd, (*obj)->body_content, (*obj)->body_length);
        }
        else logit("\n\nCHUNKED", "content.log");
Avatar billede jnusa Nybegynder
01. december 2004 - 16:33 #16
Ov, levn med strdup... testede mig frem. Har prøvet uden og scrnprnt er uden strdup. Kan jeg ikke sende pr. mail i stedet for at upload og link her på siden.
Avatar billede brilleaben Nybegynder
01. december 2004 - 16:35 #17
Jo, selvfølgelig - brisse@ping.dk
Avatar billede jnusa Nybegynder
01. december 2004 - 16:56 #18
u got mail
Jeg trykker på den satans accepter. og der sker ikke noget med pointene
Avatar billede brilleaben Nybegynder
01. december 2004 - 19:02 #19
Det er vist noget med, at du først skal markere mit navn (selvom jeg er den eneste der
har svaret (?)) ...  Så kan du acceptere.

Har iøvrigt lige sendt svar tilbage til dig :-)
Avatar billede jnusa Nybegynder
02. december 2004 - 15:48 #20
Yeah... fandt også ud af det, da IE6 ligeledes ikke ville give points :)
For en god ordens skyld, vil jeg lige fortælle hvad problemet var.
I headeren på jpg's og gif's (sikkert også andre formater), bruges 0x00 til at adskille billed-headeren fra 'kroppen'. Dette kan nemt gå galt, hvis man bruger C funktioner, der terminere ved 0x00 tegnet. Det var det, der skete i dette tilfælde. Så undgå, strlen, puts, write, strcpy, printf m.m. som ikke tager en længde med i deres parameter.
Tusinde tak til brilleaben, for at pointere det.
/jnusa
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester