Question

Je suis en train de créer un petit proxy Web en C. D'abord, je suis en train d'obtenir une page Web, envoi d'une trame GET au serveur. Je ne sais pas ce que j'ai manqué, mais je ne reçois aucune réponse. Je voudrais vraiment apprécier si vous pouvez me aider à trouver ce qui manque dans ce code.

int main (int argc, char** argv) {
   int cache_size,     //size of the cache in KiB
       port,
       port_google = 80,
       dir,
       mySocket,
       socket_google;

   char google[] = "www.google.es", ip[16];
   struct sockaddr_in socketAddr;
   char buffer[10000000];

   if (GetParameters(argc,argv,&cache_size,&port) != 0)
       return -1;

   GetIP (google, ip);
   printf("ip2 = %s\n",ip);

   dir = inet_addr (ip);
   printf("ip3 = %i\n",dir);

   /* Creation of a socket with Google */
   socket_google = conectClient (port_google, dir, &socketAddr);
   if (socket_google < 0) return -1;
   else printf("Socket created\n");

   sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
   if (write(socket_google, (void*)buffer, MESSAGE_LENGTH+1) < 0 )
       return 1;
   else printf("GET frame sent\n");

   strcpy(buffer,"\n");
   read(socket_google, buffer, sizeof(buffer));

   // strcpy(message,buffer);
   printf("%s\n", buffer);

   return 0;
}

Et ceci est l'utilisation du code I pour créer la prise. Je pense que cette partie est OK, mais je copie juste au cas où.

int conectClient (int puerto, int direccion, struct sockaddr_in *socketAddr) {
   int mySocket;
   char error[1000];

   if ( (mySocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
       printf("Error when creating the socket\n");
       return -2;
   }

   socketAddr->sin_family = AF_INET;
   socketAddr->sin_addr.s_addr = direccion;
   socketAddr->sin_port = htons(puerto);

   if (connect (mySocket, (struct sockaddr *)socketAddr,sizeof (*socketAddr)) == -1) {
       snprintf(error, sizeof(error), "Error in %s:%d\n", __FILE__, __LINE__);
       perror(error);
       printf("%s\n",error);
       printf ("-- Error when stablishing a connection\n");
       return -1;
   }
   return mySocket;
}

Merci!

Était-ce utile?

La solution

Puisque vous ne publiez pas la routine GetIP, je ne suis pas certain que votre demande de nom est correct, que des regards de celui-ci, je ne suis pas sûr que vous utilisez correctement la fonction inet_addr.

Nikolai a fait quelques très bons points (et je suis entièrement d'accord). En fait, vous GET demande est effectivement cassée, et pendant que je testais sur mon propre serveur web local Apache sur mon système, il ne fonctionne pas.

sprintf(buffer,"GET /index.html HTTP/1.1\r\n\r\n");
if (write(socket_google, (void*)buffer, LONGITUD_MSJ+1) < 0 )
    return 1;
else printf("GET frame sent\n");
...

strcpy(buffer,"\n");
read(socket_google, buffer, sizeof(buffer));

doit être remplacé par

  snprintf(buffer, sizeof(buffer), 
      "GET / HTTP/1.1\r\nHost: %s\r\nUser-Agent: TEST 0.1\r\n\r\n", 
      google);

  if (write(socket_google, buffer, strlen(buffer)+1) < 0 ) {
      close(socket_google);
      return 1;
  } else 
      printf("GET frame sent\n");
  ...

  buffer[0] = '\0';
  /* Read message from socket */
  bytes_recv = read(socket_google, buffer, sizeof(buffer));
  if (bytes_recv < 0) {
       fprintf(stderr, "socket read error: %s\n", strerror(errno));
       close(socket_google);
       exit(10);
  }

  buffer[bytes_recv] = '\0';    /* NUL character */

  /* strcpy(message,buffer); */
  printf("%s\n", buffer);

  ...

Vous devriez également close la prise avant de quitter le programme. Activer le mode standard C89 / 90 ou C99 de votre compilateur (par exemple -std=c99 pour gcc) et activer les avertissements (par exemple -Wall pour gcc), et de les lire. Et #include les fichiers d'en-tête nécessaires (en supposant Linux dans mon cas) pour les prototypes de fonction:

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>      /* for gethostbyname() */

Il y a un Castings de pointeurs et structs en ce qui concerne le nom d'hôte / adresse IP résolution, qui peut être source de confusion et lieu facile de faire une erreur, vérifiez si bien que fonctionne comme prévu, il est .

 in_addr_t ip;
 ...

 GetIP(google, &ip);   /* I changed the parameters */
 printf("IP address = %x (%s)\n", 
     ip, 
     inet_ntoa(*((struct in_addr*)&ip)));

Autres conseils

D'abord, vous n'êtes pas de vérifier combien d'octets write(2) appel effectivement écrit à la prise. La valeur de retour de l'appel vous dit que. Idem pour le read(2) . socket TCP est un flux bidirectionnel, afin règle toujours faire à la fois dans une boucle jusqu'à ce que nombre attendu d'octets est transféré, EOF est lu (retour à zéro de read(2)), ou une erreur est survenue (que vous ne vérifiez pas quand la lecture non plus).

Alors HTTP est un protocole assez complexe. Familiarisez-vous avec RFC 2616 , en particulier les codages de gestion de connexion au niveau de l'application et de transfert.

Modifier 0:

Hmm, il n'y a pas une telle chose comme proxy de "simple". Vous devez gérer plusieurs connexions (au moins client-proxy et proxy-serveur), il est probablement préférable de regarder dans select(2) / poll(2) / epoll(4) / kqueue(2) famille d'appel système, qui vous permet de multiplex E / S. Ceci est généralement combiné avec non bloquante prises. Regardez dans les bibliothèques d'aide comme libevent . Regardez comment cela se fait dans de bonnes web serveurs / proxy comme nginx . Son comme il est beaucoup pour vous faire découvrir, mais ne vous inquiétez pas, il est amusant:)

En fait, j'ai un petit proxy de mise en œuvre Web en utilisant ma bibliothèque appelée lien rzsocket lui .

L'une des choses les plus difficiles que j'ai trouvé la mise en œuvre du proxy Web, peut-être que cela pourrait aussi être votre problème, est que, pour faire fonctionner procuration correctement, je devais définir les paramètres de keep-alive faux. Une façon de le faire dans FireFox, accède about: config. adresse et le réglage de la valeur de network.http.proxy.keep-alive à false

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top