Télécharger HTTP thru sockets (C)
Récemment, j'ai commencé à prendre des ce guide à me procurer commencé sur le téléchargement de fichiers à partir d'internet. Je l'ai lu et est venu avec le code suivant pour télécharger le corps HTTP d'un site web. Le seul problème est que ça ne fonctionne pas. Le code s'arrête lors de l'appel de l'appel recv (). Il ne plante pas, il continue à courir. Est-ce de ma faute? Suis-je à l'aide de la mauvaise approche? J'ai l'intention d'utiliser le code pour ne pas le télécharger le contenu de .fichiers html, mais aussi de télécharger d'autres fichiers (zip, png, jpg, dmg ...). J'espère qu'il y a quelqu'un qui peut m'aider. C'est mon code:
#include <stdio.h>
#include <sys/socket.h> /* SOCKET */
#include <netdb.h> /* struct addrinfo */
#include <stdlib.h> /* exit() */
#include <string.h> /* memset() */
#include <errno.h> /* errno */
#include <unistd.h> /* close() */
#include <arpa/inet.h> /* IP Conversion */
#include <stdarg.h> /* va_list */
#define SERVERNAME "developerief2.site11.com"
#define PROTOCOL "80"
#define MAXDATASIZE 1024*1024
void errorOut(int status, const char *format, ...);
void *get_in_addr(struct sockaddr *sa);
int main (int argc, const char * argv[]) {
int status;
//GET ADDRESS INFO
struct addrinfo *infos;
struct addrinfo hints;
//fill hints
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
//get address info
status = getaddrinfo(SERVERNAME,
PROTOCOL,
&hints,
&infos);
if(status != 0)
errorOut(-1, "Couldn't get addres information: %s\n", gai_strerror(status));
//MAKE SOCKET
int sockfd;
//loop, use first valid
struct addrinfo *p;
for(p = infos; p != NULL; p = p->ai_next) {
//CREATE SOCKET
sockfd = socket(p->ai_family,
p->ai_socktype,
p->ai_protocol);
if(sockfd == -1)
continue;
//TRY TO CONNECT
status = connect(sockfd,
p->ai_addr,
p->ai_addrlen);
if(status == -1) {
close(sockfd);
continue;
}
break;
}
if(p == NULL) {
fprintf(stderr, "Failed to connect\n");
return 1;
}
//LET USER KNOW
char printableIP[INET6_ADDRSTRLEN];
inet_ntop(p->ai_family,
get_in_addr((struct sockaddr *)p->ai_addr),
printableIP,
sizeof(printableIP));
printf("Connection to %s\n", printableIP);
//GET RID OF INFOS
freeaddrinfo(infos);
//RECEIVE DATA
ssize_t receivedBytes;
char buf[MAXDATASIZE];
printf("Start receiving\n");
receivedBytes = recv(sockfd,
buf,
MAXDATASIZE-1,
0);
printf("Received %d bytes\n", (int)receivedBytes);
if(receivedBytes == -1)
errorOut(1, "Error while receiving\n");
//null terminate
buf[receivedBytes] = '\0';
//PRINT
printf("Received Data:\n\n%s\n", buf);
//CLOSE
close(sockfd);
return 0;
}
void *get_in_addr(struct sockaddr *sa) {
//IP4
if(sa->sa_family == AF_INET)
return &(((struct sockaddr_in *) sa)->sin_addr);
return &(((struct sockaddr_in6 *) sa)->sin6_addr);
}
void errorOut(int status, const char *format, ...) {
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
exit(status);
}
Si l'intention est de téléchargement de fichiers, pas de la mise en œuvre de HTTP, vous seriez mieux d'utiliser une bibliothèque comme cURL: curl.haxx.se
OriginalL'auteur v1Axvw | 2010-08-01
Vous devez vous connecter pour publier un commentaire.
Si vous souhaitez extraire les fichiers à l'aide de HTTP, puis libcURL est probablement votre meilleur pari en C. Cependant, si vous utilisez ce moyen pour apprendre la programmation réseau, alors vous allez avoir à apprendre un peu plus sur HTTP avant de pouvoir récupérer un fichier.
Ce que vous voyez dans votre programme actuel, c'est que vous avez besoin d'envoyer une demande explicite pour le fichier avant de pouvoir le récupérer. Je voudrais commencer par une lecture RFC2616. N'essayez pas de tout comprendre - il y a beaucoup à lire pour cet exemple. Lire la première section afin d'obtenir une compréhension de la façon dont le HTTP fonctionne, puis de lire les sections 4, 5, et 6 comprendre le format de message.
Voici un exemple de ce qu'une requête HTTP à l'stackoverflow Questions de la page ressemble à ceci:
Je crois que c'est un minimum de demande. J'ai ajouté le CRLFs explicitement à montrer qu'une ligne vide est utilisé pour mettre fin à la demande de l'en-tête de bloc comme décrit dans la RFC2616. Si vous laissez de côté le
Accept-Encoding
en-tête, puis le document sera probablement transféré comme un compressée par gzip flux depuis HTTP permet explicitement à moins que vous dire au serveur que vous ne le voulez pas.La réponse du serveur contient également des en-têtes HTTP pour les méta-données décrivant la réponse. Voici un exemple de réponse de la demande précédente:
Cet exemple simple devrait vous donner une idée de ce que vous obtenez en œuvre si vous souhaitez extraire les fichiers en utilisant le protocole HTTP. C'est le meilleur des cas, le plus simple exemple. Ce n'est pas quelque chose que je voudrais entreprendre à la légère, mais c'est probablement la meilleure façon d'apprendre et d'apprécier HTTP.
Si vous êtes à la recherche d'une manière simple d'apprendre la programmation réseau, c'est un bon moyen pour commencer. Je recommande ramasser une copie de TCP/IP Illustré, Volume 1 et UNIX, Programmation Réseau, Volume 1. Ces sont probablement la meilleure façon de vraiment apprendre à écrire des applications réseau. Je serais probablement commencer par écrire un Client FTP depuis FTP est beaucoup plus simple de protocole de commencer avec.
Si vous essayez d'apprendre les détails associés HTTP:
telnet server 80
et en tapant des requêtes à la main--verbose
et--include
options de ligne de commande de sorte que vous pouvez voir ce qui se passeJuste ne comptez pas sur la rédaction de votre propre client HTTP pour utilisation en entreprise. Vous ne voulez pas le faire, faites-moi confiance que celui qui a été le maintien d'une telle erreur pour un peu de temps maintenant...
Vous êtes tout à fait bienvenue. Je vais vous offrir quelques conseils si. En utilisant des implémentations des protocoles complexes que font les autres, est une partie importante du développement de logiciels. Je voudrais embrasser les bibliothèques comme cURL, Apache Portable Runtime, Boost, et d'autres bibliothèques populaires. L'écriture de tout soi-même est une recette pour un désastre. C'est un très bon moyen d'apprendre comment un protocole d'œuvres, mais une très mauvaise façon d'utiliser HTTP au niveau de la couche application.
J'ai été d'accord avec vous jusqu'à ce que vous avez mentionné à l'APR, qui est la plus grande abomination que j'ai jamais vu dans C...
OriginalL'auteur D.Shawley
Le problème est, vous avez à mettre en œuvre le protocole HTTP. Le téléchargement d'un fichier n'est pas juste une question de connexion au serveur, vous devez envoyer des requêtes HTTP (d'en-tête HTTP) avant d'obtenir une réponse. Après cela, vous devrez analyser les données renvoyées à bande plus les en-têtes HTTP.
Si vous êtes juste essayer de télécharger des fichiers à l'aide de C, je vous propose la cURL bibliothèque, qui ne le HTTP fonctionne pour vous.
OriginalL'auteur You
Vous devez envoyer une requête HTTP, avant d'attendre une réponse.
Vous code actuellement juste attend une réponse qui ne vient jamais.
Aussi, ne pas écrire tout en majuscules.
OriginalL'auteur Amnon