/* * Programme: client_base.c * Auteur: Paul Girard Ph.D., DIM, UQAC * Date: octobre 2000, mod sept 2004, sept 2006, jan2008 * // Modifier par: Francois-Luc Bergeron - BERF25118206 // UQAC //Client FTP * But: Exemple d'utilisation de socket TCP/IP * pour un programme client dans un environnement * environnement Solaris 5.7 sur Sun permettant * l'envoi d'un message à un serveur et de recevoir * un accusé de réseption de ce dernier. Un délai de * 1 seconde permet de visualiser le transfert à l'écran. * * Options de compilation et de link: * ===> gcc client_base.c -lsocket -lnsl -o client_base * * Exécution: 2 parametres formels: nom du serveur et no de port du serveur * =========> client_base nom_serveur #port * ex. client_base "sunens.uqac.ca" 5001 * * * Fichiers a inclure */ #include #include #include #include #include #include #include #include /* Les fonctions suivantes seront utilisées * pour la creation d'un socket, la recherche de l'adresse * reseau du serveur, la demande de connection au socket du serveur, * l'envoi et la reception de message et la * fermeture du socket. * socket, gethostbyname, connect, * read, write, close. */ #define DATA "Paquet bidon du client transmis au serveur par TCP" #define NAK "nom de fichier incorrecte.(NAK)\n" #define ACK "Fichier accepté.(ACK)\n" // le serveur accepte le nom du fichier main(argc,argv) int argc; char *argv[]; /* argv[0] pointe sur le nom du prog argv[1] pointe sur le nom du serveur argv[2] pointe sur le numero du port tcp*/ { int conn; /* descripteur de socket */ struct sockaddr_in server1; /*structure utilisee pour assigner un nom a un socket selon le format internet */ size_t length; /* #octets de la structure sockadr_in */ struct hostent *hp,*gethostbyname(); /* structure pour associer le nom de l'hote et son adresse d'apres le format internet */ struct hostent hpstruct; /* structure accédant la partie adresse du serveur */ char buf[80]; /* tampon pour la reception d'un message */ int rval; /* code de statut pour le read */ int n, i; /* compteurs temporaires */ double noctets=0; /* * 1. Validation des parametres sur la ligne de commande */ if (argc != 3) { printf("Appelez le programme ainsi: client_base nom_serveur no_port\n"); exit(1); } /* * 2. Creation d'un socket en mode TCP (sock_stream) et en suivant * les regles d'internet (AF_INET) pour le format d'adresse * avant de pouvoir transmettre */ conn = socket(AF_INET, SOCK_STREAM, 0); if (conn < 0) { perror("erreur de creation du socket conn"); exit(1); } /* * 3. Obtenir un pointeur a la structure d'adresse reseau du * serveur specifie. Le nom du serveur est pris * comme parametre formel sur la ligne de commande (argv[1]): ex. "sunens.uqac.ca" */ server1.sin_family = AF_INET; /* format internet */ hp = gethostbyname(argv[1]); /* pointeur de la structure du serveur en ecoute sur le port pointe par arg[1] */ if (hp == 0) { fprintf(stderr, "%s: hote inconnu ===>", argv[1]); exit(2); } hpstruct = *hp; /* sauvegarder les donnees hostent */ /* * 4. Remplir la partie adresse remote pour la structure du nouveau socket */ server1.sin_family = hpstruct.h_addrtype; server1.sin_port = htons(atoi(argv[2])); /* #port char => #port entier interne #port entier format reseau */ server1.sin_addr = * ((struct in_addr *) hpstruct.h_addr); /* 5. Connecter le socket local (conn) au socket du serveur specifie * par l'adresse de sa structure (server1) */ hrtime_t debut,fin; double delais; debut=gethrtime()/1000; if (connect(conn, (struct sockaddr *)&server1, sizeof(server1)) < 0) { perror("erreur de connexion"); exit(1); } /* * 5.1 saisie du nom de fichier et vérification de ce fichier, coté client. * */ FILE *fptr; char ligne[80]; char filename_local[80]; char filename_distant[80]; puts("nom du fichier a transmettre ?"); gets(filename_local); if((fptr = fopen(filename_local, "r"))==NULL) { perror("erreur d'ouverture de fichier"); exit(0); } puts("nom du fichier a enregistrer ?"); gets(filename_distant); /* * 5.2 envoi du nom de fichier, attende de validation du serveur. * */ if(write(conn, filename_distant, sizeof (filename_distant)) < 0) perror("erreur dans l'emission d'un message"); else { /* initialiser le tampon pour la reception */ if ((rval = read(conn, buf, 80)) < 0) perror("erreur de lecture du message");// si erreur if (rval == 0) //si fin de message printf("Fin de la connection\n"); buf[rval]='\0'; if (0== (strcmp( buf, NAK ))) { perror("mauvais nom de fichier123");//if NAK exit(0); } else { //else ACK.. alors envoi du fichier ligne par ligne //buf[rval]='\0'; printf(buf); /* 6 envoi du fichier, ligne par ligne. * * */ do{ fgets(ligne,80,fptr); if((noctets+=write(conn, ligne, sizeof (ligne))) < 0) perror("erreur dans l'emission du fichier"); }while(!feof(fptr)); fclose(fptr); //printf("fermeture fichier\n"); } } close(conn); fin= gethrtime()/1000; delais=(double)(fin-debut)/1000; printf("Nombre d'octets envoyés: %9.2f \n",noctets); printf("Debit = %7.2f Ko/sec \t\tTemps de transfert TCP = %9.3f msec\n", (double)(noctets*1000)/(1024*delais), delais); puts("Fin du programme client"); exit(0); /* fin du programme client */ }