Differisce tra intestazione e contenuto della risposta del server http (socket)

Voglio sapere, c‘è la possibilità di scoprire dove nella risposta Stream termina l’intestazione?

Lo sfondo della domanda è il seguente, sto usando i socket in c per ottenere il contenuto da un sito web, il contenuto è codificato in gzip. Vorrei leggere il contenuto direttamente dallo stream e codificare il contenuto gzip con zlib. Ma come faccio a sapere che il contenuto gzip è iniziato e l’intestazione http è finita.

Ho provato approssimativamente due modi che mi danno alcuni risultati, a mio avviso, strani. Per prima cosa, ho letto tutto il stream e lo ho stampato nel terminale, l’intestazione http termina con “\ r \ n \ r \ n” come mi aspettavo, ma la volta successiva, recupero la risposta una volta per ottenere l’intestazione e poi leggere il contenuto con il ciclo while, qui l’intestazione termina senza “\ r \ n \ r \ n”.

Perché? E qual è il modo giusto di leggere nel contenuto?

Ti darò il codice in modo da poter vedere come ottengo la risposta dal server.

//first way (gives rnrn) char *output, *output_header, *output_content, **output_result; size_t size; FILE *stream; stream = open_memstream (&output, &size); char BUF[BUFSIZ]; while(recv(socket_desc, BUF, (BUFSIZ - 1), 0) > 0) { fprintf (stream, "%s", BUF); } fflush(stream); fclose(stream); output_result = str_split(output, "\r\n\r\n"); output_header = output_result[0]; output_content = output_result[1]; printf("Header:\n%s\n", output_header); printf("Content:\n%s\n", output_content); 

.

 //second way (doesnt give rnrn) char *content, *output_header; size_t size; FILE *stream; stream = open_memstream (&content, &size); char BUF[BUFSIZ]; if((recv(socket_desc, BUF, (BUFSIZ - 1), 0) > 0) { output_header = BUF; } while(recv(socket_desc, BUF, (BUFSIZ - 1), 0) > 0) { fprintf (stream, "%s", BUF); //i would just use this as input stream to zlib } fflush(stream); fclose(stream); printf("Header:\n%s\n", output_header); printf("Content:\n%s\n", content); 

Entrambi danno lo stesso risultato stampandoli al terminale, ma il secondo dovrebbe stampare altre pause, almeno mi aspetto, perché si perdono dividendo la corda.

Sono nuovo di c, quindi potrei semplicemente supervisionare alcune cose facili.

Stai chiamando recv() in un ciclo finché il socket non si disconnette o fallisce (e scrivendo i dati ricevuti nel tuo stream nel modo sbagliato), memorizzando tutti i dati grezzi nel tuo buffer char* . Questo non è il modo corretto di leggere una risposta HTTP, specialmente se vengono utilizzati keep-alive HTTP (nel qual caso non si verificherà alcuna disconnessione alla fine della risposta). È necessario seguire le regole descritte in RFC 2616 . Vale a dire:

  1. Leggi fino a quando non si incontra la sequenza "\r\n\r\n" . Non leggere altri byte ancora.

  2. Analizza le intestazioni ricevute, secondo le regole nella sezione 4.4 della RFC 2616 . Ti dicono il formato effettivo dei restanti dati di risposta.

  3. Leggi i dati per il formato scoperto in # 2.

  4. Controlla le intestazioni ricevute per la presenza di una Connection: close intestazione se la risposta sta utilizzando HTTP 1.1 o la mancanza di una Connection: keep-alive intestazione Connection: keep-alive se la risposta utilizza HTTP 0.9 o 1.0. Se rilevato, chiudi la fine della connessione socket perché il server sta chiudendo la sua fine. Altrimenti, mantenere la connessione aperta e riutilizzarla per le richieste successive (a meno che non si stia utilizzando la connessione, nel qual caso chiuderla).

  5. Elabora i dati ricevuti secondo necessità.

In breve, devi fare qualcosa di più simile a questo (pseudo codice):

 string headers[]; byte data[]; string statusLine = read a CRLF-delimited line; int statusCode = extract from status line; string responseVersion = extract from status line; do { string header = read a CRLF-delimited line; if (header == "") break; add header to headers list; } while (true); if ( !((statusCode in [1xx, 204, 304]) || (request was "HEAD")) ) { if (headers["Transfer-Encoding"] ends with "chunked") { do { string chunk = read a CRLF delimited line; int chunkSize = extract from chunk line; if (chunkSize == 0) break; read exactly chunkSize number of bytes into data storage; read and discard until a CRLF has been read; } while (true); do { string header = read a CRLF-delimited line; if (header == "") break; add header to headers list; } while (true); } else if (headers["Content-Length"] is present) { read exactly Content-Length number of bytes into data storage; } else if (headers["Content-Type"] == "multipart/byteranges") { string boundary = extract from Content-Type header; read into data storage until terminating boundary has been read; } else { read bytes into data storage until disconnected; } } if (!disconnected) { if (responseVersion == "HTTP/1.1") { if (headers["Connection"] == "close") close connection; } else { if (headers["Connection"] != "keep-alive") close connection; } } check statusCode for errors; process data contents, per info in headers list;