Public feed
#892003
/*
* 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 <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <stdio.h>
/* 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 */
}