Le protocole HTTP: Client GCC


Ce programme propose une implémentation très simple d'une requête http.
  • Ce programme a été compilé et exécuté avec succé sous Aix, window95, windows 2000 et linux
  • la compilation se fait avec gcc: ggc -o clientHttp client.c
  • C'est très simple à comprendre si vous connaissez le principe de communication des sockets UNIX
  • ligne de commande: client proxy_name proxy_port host page
    e.g: si vous n'utilisez pas de proxy, faites simplement : client www.salemioche.com /index.htm
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define CONF_FILE "http.host"
#define PACKET_SIZE  1024

void requete(void);

int to_server_socket = -1;
char server_name[100]; // nom du host du serveur
int port = 80;
char request_host[PACKET_SIZE];
char request_path[PACKET_SIZE];

int main (int argc, char *argv[])
{
  struct sockaddr_in serverSockAddr;
  struct hostent *serverHostEnt;
  unsigned long hostAddr;

  if ( argc == 5 ) { // we use a proxy
   sprintf(server_name,argv[1]);
   sscanf(argv[2],"%d",&port);
   sprintf(request_host,argv[3]);
   sprintf(request_path,argv[4]);
  } else if ( argc == 3 ) { // we don't
   sprintf(server_name,argv[1]);
   sprintf(request_host,argv[1]);
   sprintf(request_path,argv[2]);
  }
  else
   exit(1);

  /* initialise a zero serverSockAddr */
  bzero((void *)&serverSockAddr,sizeof(serverSockAddr));
  /* converti l'adresse ip 9.100.1.1 en entier long */
  hostAddr = inet_addr(server_name);
  if ( (long)hostAddr != (long)-1)
    bcopy((void *)&hostAddr,(void *)&serverSockAddr.sin_addr,
          sizeof(hostAddr));
  else                /* si on a donné un nom  */
  {
    serverHostEnt = gethostbyname(server_name);
    if (serverHostEnt == NULL) {
            printf("probleme gethost\n");
            exit(1);
    }
    bcopy((void *)serverHostEnt->h_addr,
          (void *)&serverSockAddr.sin_addr,serverHostEnt->h_length);
  }
  serverSockAddr.sin_port = htons(port);   /* host to network port  */
  serverSockAddr.sin_family = AF_INET;     /* AF_*** : INET=internet */

  /* creation de la socket */
  if ( (to_server_socket = socket(AF_INET,SOCK_STREAM,0)) < 0)
  {
    printf("probleme de creation socket client\n");
    exit(2);
  }
  /* requete de connexion */
  if(connect(to_server_socket,(struct sockaddr *)&serverSockAddr,
             sizeof(serverSockAddr))<0)
  {
    printf("probleme demande de connection\n");
    exit(3);
  }

  requete();

  /* fermeture de la connection */
  shutdown(to_server_socket,2);
  close(to_server_socket);
  return 1;
}

int readn(int fd, char *ptr, int n);

void requete (void) {
char buffer[PACKET_SIZE+1];
char line[PACKET_SIZE+2];
int rc;
static unsigned char isEntete = 1;
char *finEntete;
FILE *bulk, *entete;
  sprintf(buffer,"Vide\n");
  sprintf(line,"GET %s HTTP/1.1\r\n"
    "Host: %s\r\n"
    "Accept: image/gif, image/x-xbitmap, image/jpeg,"
    " image/pjpeg, image/png, */*\r\n"
    // authentification sample
    // "Authorization: Basic cHVibGljOg\r\n"
    "\r\n"
    ,request_path,request_host);
  printf(line);

  if ( ( bulk = fopen("bulkhttp","wb")) == NULL ) {
    printf ( "can't open file to write bulk\n" );
    exit(1);
  }
  if ( ( entete = fopen("entete","wb")) == NULL ) {
    fclose(bulk);
    printf ( "can't open file to write entete\n" );
    exit(1);
  }
  send(to_server_socket,line,strlen(line)+1,0);
  do {
    rc = readn(to_server_socket,buffer,PACKET_SIZE);
    if ( isEntete == 1 ) {
     finEntete = (char *)strstr(buffer,"\r\n\r\n");
      if ( finEntete != NULL ) {
       *finEntete = 0x00;
       fwrite(buffer,1,strlen(buffer),entete);
       fwrite(finEntete+4,1,rc-strlen(buffer)-4,bulk);
       isEntete = 0;
      }
      else
       fwrite(buffer,1,rc,bulk);
      fclose(entete);
    }
    else
      fwrite(buffer,1,rc,bulk);
  } while ( rc != 0 ) ;
  fclose(bulk);
}

int readn(int fd, char *ptr, int n){
int nl, nr;

  nl = n;
  while ( nl > 0 ) {
    nr = read(fd,ptr,nl);
    if (nr < 0 )
            return nr;     /*error*/
    else
            if ( nr == 0 )
                    break;
    nl -= nr;
    ptr += nr;
  }
  *ptr = 0x00;
  return (n-nl);
}