title: How to download a file from http using C?
body: <p>I spent the last days trying to figure out how to download a file from an URL.
  This is my first challenge with socket and I'm using it to have an understanding of protocols so I would like to do it without cURL libraries and only in C language!!
  I searched a lot....now I'm able to printf the source code of a page but I think it's different with a file, I don't have only to put the received data from a buffer to a file, right?
  any tips?</p>
  
  <pre><code>#include &lt;sys/socket.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;arpa/inet.h&gt;
  
  int main(void)
  {
      char domain[] = "www.sstatic.net", path[]="stackexchange/img/logos/so/so-logo-med.png"; //example 
      int sock, bytes_received;  
      char send_data[1024],recv_data[9999], *p;
      struct sockaddr_in server_addr;
      struct hostent *he;
      FILE *fp;
  
      he = gethostbyname(domain);
      if (he == NULL){
         herror("gethostbyname");
         exit(1);
      }
  
      if ((sock = socket(AF_INET, SOCK_STREAM, 0))== -1){
         perror("Socket");
         exit(1);
      }
      server_addr.sin_family = AF_INET;     
      server_addr.sin_port = htons(80);
      server_addr.sin_addr = *((struct in_addr *)he-&gt;h_addr);
      bzero(&amp;(server_addr.sin_zero),8); 
      if (connect(sock, (struct sockaddr *)&amp;server_addr,sizeof(struct sockaddr)) == -1){
         perror("Connect");
         exit(1); 
      }
  
      snprintf(send_data, sizeof(send_data), "GET /%s HTTP/1.1\r\nHost: /%s\r\n\r\n", path, domain);
      //printf("%s\n", send_data);
      send(sock, send_data, strlen(send_data), 0); 
      printf("Data sended.\n");  
  
      fp=fopen("received_file","wb");
  
      bytes_received = recv(sock, recv_data, 9999, 0);
      recv_data[bytes_received] = '\0';
      printf("Data receieved.\n");
      printf("%s\n", recv_data);
  
      p = strstr(recv_data, "\r\n\r\n");  //to find "\r\n\r\n" sequence and put the pointer p after that
      p=p+4;
  
      fwrite(p,strlen(p),1,fp);       
  
      close(sock);
      fclose(fp);
  
  return 0;
  } 
  </code></pre>
  
  <p><strong>UPDATE 1</strong> thanks to milevyo for some improvements!
  It works good with a txt file but it doesn't with other kinds of file (png in this case)</p>
  
  <pre><code>#include &lt;sys/socket.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;arpa/inet.h&gt;
  
  int main(void){
  
      //char domain[] = "www.gnu.org", path[]="/licenses/gpl.txt"; //example 
      char domain[] = "sstatic.net", path[]="stackexchange/img/logos/so/so-logo-med.png"; //example 
          int sock, bytes_received;  
      char send_data[1024],recv_data[9999];
      struct sockaddr_in server_addr;
      struct hostent *he;
      FILE *fp;
  
      he = gethostbyname(domain);
      if (he == NULL){
         herror("gethostbyname");
         exit(1);
      }
  
      if ((sock = socket(AF_INET, SOCK_STREAM, 0))== -1){
         perror("Socket");
         exit(1);
      }
      server_addr.sin_family = AF_INET;     
      server_addr.sin_port = htons(80);
      server_addr.sin_addr = *((struct in_addr *)he-&gt;h_addr);
      bzero(&amp;(server_addr.sin_zero),8); 
  
      printf("Connecting ...\n");
      if (connect(sock, (struct sockaddr *)&amp;server_addr,sizeof(struct sockaddr)) == -1){
         perror("Connect");
         exit(1); 
      }
  
      printf("Sending data ...\n");
  
      snprintf(send_data, sizeof(send_data), "GET /%s HTTP/1.1\r\nHost: /%s\r\n\r\n", path, domain);
  
      if(send(sock, send_data, strlen(send_data), 0)==-1){
          perror("send");
          exit(2); 
      }
      printf("Data sent.\n");  
  
      fp=fopen("received_file","wb");
      printf("Recieving data...\n\n");
      while((bytes_received = recv(sock, recv_data, 9999, 0))&gt;0){
          if(bytes_received==-1){
              perror("recieve");
              exit(3);
          }
          recv_data[bytes_received] = '\0';
  
          fwrite(recv_data,bytes_received,1,fp);
          printf("%s", recv_data);
      }
  
  
  
      close(sock);
      fclose(fp);
      printf("\n\nDone.\n\n");
      return 0;
  }
  </code></pre>
  
  <p>this code produce a 334 bytes file (instead of 12,4kb of the original file) with this inside:</p>
  
  <pre><code>HTTP/1.1 400 Bad Request
  Date: Sat, 28 Nov 2015 16:20:45 GMT
  Content-Type: text/html
  Content-Length: 177
  Connection: close
  Server: -nginx
  CF-RAY: -
  
  &lt;html&gt;
  &lt;head&gt;&lt;title&gt;400 Bad Request&lt;/title&gt;&lt;/head&gt;
  &lt;body bgcolor="white"&gt;
  &lt;center&gt;&lt;h1&gt;400 Bad Request&lt;/h1&gt;&lt;/center&gt;
  &lt;hr&gt;&lt;center&gt;cloudflare-nginx&lt;/center&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>somebody knows how to fix this "400 Bad Request"?</p>