begin process at 2012 02 10 01:06:51
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Réseaux & Internet

 > TRANSFERT DE FICHIER VIA SOCKET UDP

TRANSFERT DE FICHIER VIA SOCKET UDP


 Description

Ce programme compose de deux code; le serveur qui attend des appels de clients (pour montrer comment on fait pour synchronise les appels on accepte pas plus de 4 clients en meme temps dans le serveur); les requetes des clients est composé de deux messages le premier est le nom du fichier a transferer le deuxieme la chaine a chreche dans le fichier.
On plus de sa le programme emule une connexion TCP on envoyant des validations pour chaque envoi ou recpetion de message, ce qui permet de reenvoyer les paquets perdus.

Source

  • //////////////////////////////////////////////////////////////////////
  • // Code du serveur //
  • //////////////////////////////////////////////////////////////////////
  • /***************************************************************************/
  • /* El Antri Abdellah */
  • /* Sous licence GNU */
  • /***************************************************************************/
  • /**************************************************************************/
  • /* Rmarque importante */
  • /* Le serveur créé des fichiers log pour chaque client et un historique */
  • /* des connexions directement dans la racine / par consequent il faut */
  • /* ilo faut avoir les privileges root */
  • /**************************************************************************/
  • /* Marche sous linux/unix */
  • /* Compilation: cc fudps.c -o serveur -lpthreqd */
  • /* Execution: ./serveur 1200 */
  • #include <time.h>
  • #include <arpa/inet.h>
  • #include <netdb.h>
  • #include <dirent.h>
  • #include <sys/stat.h>
  • #include <sys/socket.h>
  • #include <sys/types.h>
  • #include <string.h>
  • #include <unistd.h>
  • #include <stdio.h>
  • #define vrai 1
  • #define faux 0
  • // Cette constante permet de specifie la longueur
  • // maximal d'un chemin specifiant un repertoire
  • #define MAX_REP_CHEMIN 2048
  • // Cette constante desgine le nombre de thread autorise a cree
  • #define MAX_THREAD 4
  • // Ddefinie la long maximal du buffer
  • #define MAX_BUF 2048
  • // Declaraation des variables globales utilise
  • int num_libre;
  • // Tableau d'identificateur
  • pthread_t th_id[MAX_THREAD];
  • // Tableau pour indique les identificateur deja pris
  • int th_occupe [MAX_THREAD];
  • // Fichier contenant l'historique des connexions et des dmandes de connexion
  • FILE *hist;
  • // Declaration des fonctions et procedures
  • // utiliser par notre serveur
  • void section_critique(FILE *);
  • int cree_socket(int, FILE * );
  • char * cherche_fichier(char *, FILE *);
  • void * th_trait(void *);
  • // Procedure principale
  • int main (int argc , char ** argv)
  • {
  • // Descripteur du serveur
  • int serveur;
  • // Adresse du client
  • // Utilise par recvfrom pour recevoir les
  • // informations du client qui a envoye une
  • // demande de connexion
  • struct sockaddr_in client;
  • // Longueur de la structure utilise par client
  • int long_client;
  • // Pour le parcour du tabbleau des identificateurs des thread
  • int i;
  • // utilise pour guarder la Valeur de retour de recvfrom
  • int recue;
  • // Utiliser pour guarder la valeur de retour de sendto
  • int envoye;
  • // Utilise pour la lecture de la demande de connexion
  • char *buf;
  • int long_buf;
  • // Pour lire la date
  • time_t temp;
  • // Contient le chemin du fichier historique
  • char nom_hist[MAX_REP_CHEMIN + 1];
  • system("clear");
  • printf("\n Arguments de la ligne de commande ... ");
  • if (argc != 2)
  • {
  • printf(" [FAILED]");
  • printf("\n Usage: serveur num_proto\n");
  • exit(1);
  • }
  • printf(" [OK]");
  • strcpy(nom_hist, "/historique");
  • printf("\n Creation du fichier %s ... ",nom_hist);
  • hist = fopen(nom_hist,"w+");
  • if(hist == NULL)
  • {
  • printf(" [FAILED]\n");
  • perror("Cause");
  • exit(1);
  • }
  • printf(" [OK]\n");
  • time(&temp);
  • fprintf(hist," -------------------------------------------------\n");
  • fprintf(hist,"| Ce fichier contient l'historique des connexions |\n");
  • fprintf(hist," -------------------------------------------------\n");
  • fprintf(hist," Date de creation: %s \n ", ctime(&temp) );
  • // Initialisation du buffer
  • // On va essayer d'alloue MAX_BUF octet
  • printf("\n Allocation du buffer ... ");
  • fprintf(hist, "\n Allocation du buffer ... ");
  • buf = (char *)malloc(MAX_BUF);
  • if(buf == NULL)
  • {
  • printf("\n Impossible d'alloue de l'espace pour le buffer");
  • // Sans le buffer on ne peut rien faire
  • exit(1);
  • }
  • printf(" [OK]");
  • fprintf(hist, " [OK]");
  • // Initialisation du tableau des threads
  • printf("\n Initialisation du tableau d'id de thread ... ");
  • fprintf(hist, "\n Initialisation du tableau d'id de thread ... ");
  • for (i = 0; i < 4; i++)
  • {
  • th_occupe[i] = -1;
  • }
  • printf(" [OK]");
  • fprintf(hist, " [OK]");
  • // Initialisation num_libre a 0
  • num_libre = 0;
  • // creation du socket
  • fprintf(hist, "\n Creation de socket sur le port %d... ",atoi(argv[1]));
  • printf("\n Creation de socket sur le port %d... ",atoi(argv[1]));
  • serveur = cree_socket(atoi(argv[1]),hist);
  • if(serveur == -1)
  • {
  • printf("\n Un probleme a interrompu la creation du socket.\n");
  • exit(1);
  • }
  • printf("\n \t Le serveur va entre dans une boucle infini \n");
  • printf(" \t ========================================= ");
  • ////////////////////////////////////////////////////////////
  • // Boucle de gestion des connexions //
  • ///////////////////////////////////////////////////////////
  • while(vrai)
  • {
  • fflush(stdout);//vidage de la sortie standard
  • printf("\n \t **************************************************");
  • printf("\n \t *** Attente des demandes de connexion ***");
  • printf("\n \t **************************************************");
  • printf("\n");
  • // Le serveur attend une demande de connexion
  • fprintf(hist, "\n Attente de demande de connexion ... ");
  • long_buf = strlen("connect");
  • recue =
  • recvfrom(serveur, buf, long_buf , 0,
  • (struct sockaddr*)&client, &long_client);
  • if (recue < 0)
  • {
  • fprintf(hist, " [FAILED]\n");
  • perror("Cause");
  • // S'il y a une erreur de reception en arrete tout
  • exit(1);
  • }
  • fprintf(hist, " [OK]");
  • // On doit recupere les informations du client
  • // qui a demande une connexion
  • printf("\n %s:%u demande la connexion au serveur ...",
  • inet_ntoa(client.sin_addr),ntohs(client.sin_port));
  • time(&temp);
  • fprintf(hist, "\n Une demande de connexion est recue:\n");
  • fprintf(hist, " _==================================_\n");
  • fprintf(hist, "\t * Date de connexion: %s", ctime(&temp));
  • fprintf(hist, "\t * Famille du Socket client: %x\n", ntohs(client.sin_family));
  • fprintf(hist, "\t * Port client: %u\n", ntohs(client.sin_port));
  • fprintf(hist, "\t * IP client: %s\n", inet_ntoa(client.sin_addr));
  • if(strcmp(buf,"connect") == 0)
  • {
  • fprintf(hist, "\n Le client a envoye %s.", buf);
  • fprintf(hist, " ... Requete valide");
  • }
  • else
  • {
  • fprintf(hist, "\n Requete inconnu: Attendu connect recue %s", buf);
  • continue ;
  • }
  • // Validation de la demande par un OK
  • // Ceci n'est pas necessaire en mode connecte
  • // car c'est la commande accepte qui realise cette tache
  • fprintf(hist,
  • "\n Le serveur envoi une reponse au %s:%u ...",
  • inet_ntoa(client.sin_addr),ntohs(client.sin_port));
  • long_client = sizeof(client);
  • if(num_libre > 3)
  • {
  • strcpy(buf,"NO");
  • long_buf = strlen("NO") + 1;
  • envoye =
  • sendto(serveur,buf,long_buf,0,
  • (struct sockaddr *)&client,
  • long_client);
  • if(envoye < 0)
  • {
  • fprintf(hist, " [FAILED]\n");
  • perror("Cause");
  • continue ;
  • }
  • printf("\n Connexion du %s:%u refuse: depacement de capacite \n",
  • inet_ntoa(client.sin_addr),ntohs(client.sin_port));
  • fprintf(hist, " [OK]\n");
  • fprintf(hist,"\n|**************************************************|");
  • fprintf(hist,"\n DEPACEMENT DE CAPACITE DU SERVEUR ");
  • fprintf(hist, "\n Connexion du client %s:%u refuse ",
  • inet_ntoa(client.sin_addr),
  • ntohs(client.sin_port));
  • fprintf(hist,"\n|**************************************************|");
  • }
  • else
  • {
  • strcpy(buf,"OK");
  • long_buf = strlen("OK") + 1;
  • envoye =
  • sendto(serveur,buf,long_buf,0,
  • (struct sockaddr *)&client,
  • long_client);
  • if(envoye < 0)
  • {
  • fprintf(hist," [FAILED]\n");
  • perror("Cause");
  • continue;
  • }
  • fprintf(hist, " [OK]\n");
  • num_libre ++;
  • // On cherche un identificateur libre
  • for(i = 0; i < 4; i++)
  • if(th_occupe[i] == -1)
  • {
  • // La structure special contient le nom de fichier
  • // la chaine a recherche
  • // et l'adresse du client
  • // creation du thread associe au client
  • fprintf(hist, "\n Creation de thread ... ");
  • if(
  • pthread_create(&th_id[i],
  • NULL,(void *) th_trait,
  • (void *)&client) != 0
  • )
  • {
  • fprintf(hist, " [FAILED]\n");
  • exit(1);
  • }
  • th_occupe[i] = th_id[i];
  • break;
  • }
  • }
  • freopen(nom_hist,"a+",hist);
  • }// while(true)
  • }
  • // Thread dedie pour la recherche de fichier
  • // Et la recherche des motifs dans un fichier
  • void * th_trait(void *client_addr)
  • {
  • // Descripteur de fichier
  • // utilise par fopen pour la lecture de fichier
  • // cherche dans le cas ou il existe
  • FILE *df;
  • // Descripteur de fichier log pour chaque thread
  • FILE *log;
  • char nom_log[MAX_BUF];
  • // Descripteur du socket serveur
  • // car chaque thread va avoir un numero de port
  • // speciale pour communiquer avec sont client
  • // ceci n'est pas necessaire dans le mode connecte
  • // puisque accepet retourne un identificateur nouveau
  • // pour chaque demande de connexion
  • int serveur;
  • // longuer de la structure sockaddr client
  • int long_client;
  • // utilise pour recuperer les valeurs de retour
  • // des fonctions recvfrom et sendto
  • int envoye, recue;
  • // Tampon de lecture ecriture
  • char *buf;
  • // Pour specifie la longueur du bufer
  • int long_buf;
  • // Stocke le nom de fichier envoye par le client
  • char nom_fichier[MAX_REP_CHEMIN];
  • // Stocke le chemin d'acce au fichier
  • // retourne par la fonction recherche_fichier
  • char chemin[MAX_REP_CHEMIN];
  • // Stocke la chaine a cherche dans le fichier
  • char motif[MAX_BUF];
  • // ndice indiquant si le motif a ete trouve ou pas
  • int motif_trouve = -1;
  • // Pour le parcour du tableau de thread
  • int i;
  • // Pour compter le nombre des bloque envoye au client;
  • int num_bloc = 0;
  • // Utilise pour savoir la longueur lu par la fct read
  • int long_lu=0;
  • struct sockaddr_in *client = (struct sockaddr_in *)client_addr;
  • // Pour obtenir le repertoire courant du travail
  • char rtc[MAX_REP_CHEMIN];
  • // Creation de thread reussi
  • sprintf(nom_log,"/serveur%s:%u.log",
  • inet_ntoa(client->sin_addr),ntohs(client->sin_port));
  • printf("\n -> Pour les details de transfert voir le fichier: %s", nom_log);
  • log = fopen(nom_log ,"w+");
  • if(log == NULL)
  • {
  • printf("\n Erreur d'ouverture du fichier log.\n");
  • perror("Cause");
  • pthread_exit(1);
  • }
  • fprintf(log," -----------------------------------------------------\n");
  • fprintf(log,"| Fichier log generer automatiquement par le serveur |");
  • fprintf(log,"\n -----------------------------------------------------\n");
  • fprintf(log, "\n Le thread %d va s'occupe de la demande du client %s\n",
  • pthread_self(),inet_ntoa(client->sin_addr));
  • // Essayer d'allouer le buffer
  • buf = (char *)malloc(MAX_BUF);
  • if (buf == NULL)
  • {
  • fprintf(log,"\n Impossible d'alloue le buffer.\n",
  • pthread_self());
  • fprintf
  • (log, "\n Arret du trait associe su client %s:%u \n",
  • inet_ntoa(client->sin_addr),
  • ntohs(client->sin_port)
  • );
  • fclose(log);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • long_buf = MAX_BUF;
  • long_client = sizeof(client);
  • // Creation de socket pour le thread
  • fprintf(log, " Creation de socket ... ",pthread_self());
  • // Creation d'un nouveau socket pour chaque thread
  • // avec un numero de port = num_port_client + 1
  • serveur = cree_socket(ntohs(client->sin_port)+1, log);
  • if(serveur < 0)
  • {
  • fclose(log);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • // Attente de messages des clients
  • // On attend un nom de fichier a cherhe
  • fprintf(log, "\n Attente du nom de fichier a cherche ... ",
  • pthread_self());
  • memset(buf,0,strlen(buf));
  • recue =
  • recvfrom(
  • serveur, buf, long_buf , 0,
  • (struct sockaddr*)client, &long_client
  • );
  • if (recue < 0)
  • {
  • fprintf(log, " [FAILED]");
  • perror("Cause");
  • fclose(log);
  • close(serveur);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • fprintf(log, " [OK]");
  • strcpy(nom_fichier,buf);
  • fprintf(log, "\n Le fichier cherche est: %s", nom_fichier);
  • // On attend la motif a cherche dans le fichier
  • fprintf(log, "\n Attente du motif a cherche ... ",pthread_self());
  • memset(buf,0,strlen(buf));
  • recue =
  • recvfrom(
  • serveur, buf, long_buf , 0,
  • (struct sockaddr*)client, &long_client
  • );
  • if (recue < 0)
  • {
  • fprintf(log," [FAILED]\n");
  • perror("Cause");
  • fclose(log);
  • close(serveur);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • strcpy(motif, buf);
  • fprintf(log, " [OK]");
  • fprintf(log, " \n Le motif cherche est: %s", motif);
  • // Recherche du fichier et recuperation de sont chemin
  • // dans le cas ou il existe
  • fprintf(log, "\n Recherche du fichier %s ... ",nom_fichier);
  • memset(chemin,0,strlen(chemin));
  • strcpy(chemin,cherche_fichier(nom_fichier,log));
  • if(!strcmp(chemin,"NO_EXIST"))
  • {
  • fprintf(log, "\n Le fichier cherche n'existe pas ... ");
  • // On envoi un message pour prevenir le client
  • // que le fichier qu'il a demande n'existe pas
  • // dans le serveur
  • fprintf(log, "\n Envoyer 'NO_EXIST' au client ... ");
  • strcpy(buf,"NO_EXIST");
  • long_buf = strlen("NO_EXIST") + 1;
  • envoye =
  • sendto(serveur,buf,long_buf,0,
  • (struct sockaddr *)client,
  • long_client);
  • if(envoye < 0)
  • {
  • fprintf(log," [FAILED]");
  • perror("Cause");
  • }
  • fprintf(log," [OK]");
  • close(serveur);
  • fclose(log);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • // Si on est arrive ici, ca veut dir que le fichier existe
  • fprintf(log,"\n Le fichier existe et sont chemin est: %s\n",chemin);
  • printf("\n Le fichier existe et sont chemin est: %s\n",chemin);
  • fprintf(log, "\n Envoyer 'EXIST' au client ... ");
  • strcpy(buf,"EXIST");
  • long_buf = strlen("EXIST") + 1;
  • envoye =
  • sendto(serveur,buf,long_buf,0,
  • (struct sockaddr *)client,
  • long_client);
  • if(envoye < 0)
  • {
  • perror("Cause");
  • close(serveur);
  • fclose(log);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • // On ouvre le fichier pour lecture
  • // la fonction fopen nous retourne un descripteur
  • // qui va etre utilise par la fonction fscanf;
  • fprintf(log, "\n Debut de transfert:");
  • fprintf(log, "\n ___________________");
  • df = fopen(chemin,"r+");
  • if(df != NULL)
  • {
  • // Tanque fin de fichier non atteinte on envoi un bloque de donne de taille
  • // strlen(buf) au client qui possede l'adresse client
  • while(!feof(df))
  • {
  • num_bloc ++;
  • if((long_lu = fread(buf,1,MAX_BUF,df)) < 0)
  • {
  • fprintf(log, "\n Erreur de lecture de fichier.\n");
  • perror("Cause");
  • break;
  • }
  • buf[long_lu] = '\0';
  • // La recherche du motif dans le buffer courant
  • if(strstr(buf, motif))
  • {
  • motif_trouve = num_bloc;
  • }
  • fprintf(log,"\n Lecture d'un bloque avec succe.");
  • do
  • {
  • fprintf(log,
  • "\n\t Envoi du bloc N %d ",num_bloc);
  • long_buf = strlen(buf)+1;
  • envoye =
  • sendto(
  • serveur,buf, long_buf, 0,
  • (struct sockaddr *)client, long_client
  • );
  • if(envoye < 0)
  • {
  • fprintf(log, "\n Erreur d'envoi de donne. \n");
  • perror("Cause");
  • continue;
  • }
  • fprintf(log,"\n\t Les donnees on ete envoyees avec succe.");
  • fprintf(log, "\n Attente de validation par le client ... ");
  • memset(buf,0,strlen(buf));
  • recue =
  • recvfrom(serveur, buf, long_buf,0,
  • (struct sockaddr *)client, &long_client);
  • if(recue < 0)
  • {
  • fprintf(log," [FAILED]");
  • continue;
  • }
  • fprintf(log," [OK]");
  • if (!strcmp(buf,"OK"))
  • {
  • fprintf(log,
  • "\n Le bloque N %d a ete recue par le client avec succe.",num_bloc);
  • break;
  • }
  • else if(!strcmp(buf,"NO"))
  • {
  • fprintf(log,
  • "\n Le client a demande la retransmission du bloc N %d",
  • num_bloc);
  • continue;
  • }
  • }while (vrai); /* do d'envoi de bloc*/
  • } /* while(!feof(df))*/
  • } /*if(df != NULL)*/
  • else
  • {
  • fprintf(log,
  • "\n Un probleme est survennu lors de l'ouverture du fichier.");
  • perror("Cause");
  • strcpy(buf,"$ERREUR$");
  • long_buf = strlen(buf);
  • sendto(serveur, (char *) buf, long_buf, 0,
  • (struct sockaddr *)client, long_client);
  • fclose(log);
  • close(serveur);
  • section_critique(log);
  • pthread_exit(1);
  • }
  • strcpy(buf, "$FIN$");
  • long_buf = strlen(buf) + 1;
  • fprintf(log,"\n Envoye $FIN$ au client %s:%u ... ", inet_ntoa(client->sin_addr),
  • ntohs(client->sin_port));
  • envoye =
  • sendto(serveur, (char *) buf, long_buf, 0,
  • (struct sockaddr *)client, long_client);
  • if(envoye < 0)
  • {
  • printf(" [FAILED]");
  • fprintf(log, " [FAILED]");
  • perror("CAUSE");
  • }
  • else
  • {
  • fprintf(log, " [OK]");
  • printf("\n Envoi du fichier a ete termine avec succe");
  • fprintf(log, "\n\t\t ------------------------ ");
  • fprintf(log, "\n\t\t |Envoi du fichier termine| ");
  • fprintf(log, "\n\t\t ------------------------ ");
  • fprintf(log,"\n Envoyer la reponse indiquant si le motif a ete trouve ...");
  • if(motif_trouve >= 0)
  • {
  • memset(buf,0,MAX_BUF);
  • // Le serveur renvoi une reponse indiquant le numero de bloque
  • // qui contient la premiere occurence du motif cherche
  • sprintf(buf,"\n Le motif cherche existe dans le bloc %d:",motif_trouve);
  • long_buf = strlen(buf) + 1;
  • }
  • else
  • {
  • sprintf(buf,"\n Le motif cherche n'existe pas dans le fichier.");
  • long_buf = strlen(buf) + 1;
  • long_buf = strlen("\n Le motif n'existe pas dans le fichier.") + 1;
  • }
  • envoye =
  • sendto(serveur, (char *) buf, long_buf, 0,
  • (struct sockaddr *)client, long_client);
  • if(envoye < 0)
  • {
  • fprintf(log, " [FAILED]");
  • }
  • else
  • {
  • fprintf(log, " [OK]");
  • fprintf(log,"%s",buf); // Le motif existe ou n'existe pas
  • fprintf(log, " \n Reponse concernant le motif ... ");
  • recue =
  • recvfrom(serveur, (char *) buf, long_buf, 0,
  • (struct sockaddr *)client, &long_client);
  • if(recue < 0)
  • {
  • fprintf(log, " [FAILED]");
  • perror("CAUSE");
  • }
  • else
  • {
  • fprintf(log, " [OK]");
  • printf(
  • "\n La requete du client %s:%u a ete traite avec succe.", inet_ntoa(client->sin_addr),
  • ntohs(client->sin_port));
  • fprintf(log,
  • "\n La requete du client %s:%u a ete traite avec succe.",
  • inet_ntoa(client->sin_addr),
  • ntohs(client->sin_port));
  • }
  • }
  • }
  • fclose(log);
  • fclose(df);
  • close(serveur);
  • section_critique(log);
  • return NULL;
  • }
  • ///////////////////////////////////////////////////////////////////////////
  • // Cette procedure permet de liberer un identificateur de decrementer //
  • // le nombre de clients qui se trouve dans le serveur //
  • /////////////////////////////////////////////////////////////////////////
  • void section_critique(FILE *log)
  • {
  • int i;
  • pthread_mutex_t mut;
  • // Initialisation du verrou
  • // Cette fonction retourne toujour 0
  • fprintf(log, "\n Initialisation du verrou ... ");
  • pthread_mutex_init(&mut, NULL);
  • fprintf(log, " [OK]\n");
  • // Section critique
  • fprintf(log, "\n Debut de la section critique ... ");
  • pthread_mutex_lock(&mut);
  • // Decrement le nombre de client
  • num_libre --;
  • // libere l'identificateur de thread
  • for(i = 0; i < 4; i ++)
  • if(th_occupe[i] == pthread_self())
  • th_occupe[i] = -1;
  • pthread_mutex_unlock(&mut);
  • fprintf(log, "\n Fin de la section critique ... ");
  • // Fin de la section critique
  • }
  • ///////////////////////////////////////////////////////////////////////////
  • // Cette fonction permet de cree un Socket //
  • // Ca valeur de retour est un descripteur dans la table des descripteur //
  • // du processus c'est pour cela qu'il faut un bind pour quelle soit //
  • // definie aupres du systeme //
  • /////////////////////////////////////////////////////////////////////////
  • int cree_socket(int port, FILE *hist)
  • {
  • struct sockaddr_in serveur_addr;
  • int serveur;
  • // Creation du socket
  • serveur = socket(AF_INET, SOCK_DGRAM,0);
  • if(serveur < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • return -1;
  • }
  • fprintf(hist, " [OK]");
  • // La famille a laquelle appartient le socket
  • serveur_addr.sin_family = AF_INET;
  • // Adresse specifique qui permet de dir au systeme
  • // que je suis en ecoute sur tout les adresse IP entrantes
  • serveur_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  • // Le port utilise par le socket
  • serveur_addr.sin_port = htons(port);
  • fprintf(hist, "\n Attachement du socket avec une adresse ip/port ... ");
  • // Attachement du socket au systeme
  • if(bind(serveur, (struct sockaddr *) &serveur_addr, sizeof(serveur_addr)) < 0)
  • {
  • fprintf(hist, " [FAILED]");
  • perror("Cause");
  • return -1;
  • }
  • fprintf(hist, " [OK]\n");
  • return serveur;
  • }
  • ///////////////////////////////////////////////////////////////////////////
  • // Cette fonction permet de cherche un fichier //
  • // dans l'arborescence du systemes et de voir si ce fichier //
  • // contient la chaine recherche //
  • ///////////////////////////////////////////////////////////////////////////
  • char * cherche_fichier(char *nom, FILE * log)
  • {
  • static int trouve = faux;
  • // Pointeur sur descripteur de repertoire
  • DIR* rep;
  • // Pointeur sur une entree repertoire
  • struct dirent* entree;
  • // Repertoire de travail courant
  • char rtc[MAX_REP_CHEMIN + 1], sauv[MAX_REP_CHEMIN + 1];
  • //Chemin complet de notre fichier
  • static char chemin[MAX_REP_CHEMIN + 1];
  • // Utilise par stat() pour teste le type des entree
  • struct stat rep_stat;
  • char pile[MAX_REP_CHEMIN][MAX_REP_CHEMIN];
  • int som = 0;
  • strcpy(pile[som],"/");
  • som++;
  • do {
  • som --;
  • strcpy(sauv,pile[som]);
  • if (chdir(sauv) == -1)
  • {
  • fprintf(log, "\n %s",sauv);
  • fprintf(log," \n Erreur lors du changement de repertoire ...");
  • strcpy(chemin,"NO_EXIST");
  • return chemin;
  • }
  • fprintf(log, "\n Recherche dans %s: ", sauv);
  • // ouvrir le repertoir pour lecture
  • rep = opendir(".");
  • if (!rep)
  • {
  • fprintf(log, "\n Impossible de lire le repertoire %s.\n ", sauv);
  • perror("Cause");
  • strcpy(chemin,"NO_EXIST");
  • return chemin;
  • }
  • ///////////////////////////////////////////////////////////////////////
  • // Parcour du repertoire courant ainsi que tout les sous repertoire //
  • ///////////////////////////////////////////////////////////////////////
  • do
  • {
  • entree = readdir(rep);
  • if(entree == NULL)
  • {
  • fprintf(log, "\n Le parcour de %s est termine.\n",sauv);
  • break;
  • }
  • if(entree != NULL)
  • {
  • fprintf(log, "\n Entree courante est: %s", entree->d_name);
  • if ( entree->d_name && !strcmp(entree->d_name,nom))
  • {
  • if (getcwd(rtc, MAX_REP_CHEMIN) == NULL)
  • {
  • perror("Cause");
  • strcpy(chemin,"NO_EXIST");
  • return chemin;
  • }
  • if(strcmp(rtc,"/"))
  • strcat(rtc,"/");
  • strcat(rtc,entree->d_name);
  • strcpy(chemin,rtc);
  • // retourne le chemin d'acce complet du fichier
  • fprintf(log, "\n Le chemin du fichier cherche est: %s\n",
  • chemin);
  • return chemin;
  • }
  • // on evite les repertoires systemes
  • // si vous voulez effectue une recherche dans ses repertoires
  • // il faut les supprimes, mais le temps de recherche augmentera
  • // considerablement
  • if(strcmp(entree->d_name,"Recycled") == 0)
  • continue;
  • if(strcmp(entree->d_name,"dev") == 0)
  • continue;
  • if(strcmp(entree->d_name,"proc") == 0)
  • continue;
  • if(strcmp(entree->d_name,"root") == 0)
  • continue;
  • if(strcmp(entree->d_name,"mnt") == 0)
  • continue;
  • if(strcmp(entree->d_name,"lib") == 0)
  • continue;
  • if(strcmp(entree->d_name,"usr") == 0)
  • continue;
  • if(strcmp(entree->d_name,"etc") == 0)
  • continue;
  • if (strcmp(entree->d_name, ".") == 0)
  • continue;
  • if (strcmp(entree->d_name, "..") == 0)
  • continue;
  • if(entree->d_name != NULL)
  • if ( stat(entree->d_name, &rep_stat) == -1)
  • {
  • continue;
  • }
  • // On teste si l'entre courante est un repertoir
  • if (S_ISDIR(rep_stat.st_mode))
  • {
  • if(som < MAX_REP_CHEMIN )
  • {
  • if (getcwd(rtc, MAX_REP_CHEMIN) == NULL)
  • {
  • perror("Cause");
  • strcpy(chemin,"NO_EXIST");
  • return chemin;
  • }
  • if(strcmp(rtc,"/"))
  • strcat(rtc,"/");
  • strcat(rtc,entree->d_name);
  • if(strcmp(rtc, sauv) != 0) // Eviter les autoreferences
  • {
  • strcpy(pile[som],rtc);
  • som++;
  • }
  • }
  • else
  • {
  • fprintf(log, "\n Pile pleine ... arret de recherche.");
  • strcpy(chemin,"NO_EXIST");
  • return chemin;
  • }
  • } // if (S_DIR)
  • } // if(entree =! null )
  • }while(vrai);
  • closedir(rep);
  • }while(som > 0);
  • strcpy(chemin,"NO_EXIST");
  • return chemin;
  • }
  • //////////////////////////////////////////////////////////////////////
  • // Code du client //
  • //////////////////////////////////////////////////////////////////////
  • /***************************************************************************/
  • /* El Antri Abdellah */
  • /* Sous licence GNU */
  • /***************************************************************************/
  • /* Pour la plate formae unix/linux */
  • /* Compilation: cc fudpc.c -o client */
  • /* Execution: ./client adresse_serveur num_protocol */
  • #include <arpa/inet.h>
  • #include <sys/socket.h>
  • #include <sys/types.h>
  • #include <netdb.h>
  • #include <dirent.h>
  • #include <sys/stat.h>
  • #include <string.h>
  • #include <unistd.h>
  • #include <stdio.h>
  • #define vrai 1
  • #define faux 0
  • // Numero du port du serveur
  • #define SERV_PORT 1200
  • // taille maximal du buffer
  • #define MAX_BUF 2048
  • // Descripteur du fichier cree pour la reception
  • FILE *fd;
  • // Le nom sous lequel le fichier transferer sera garder
  • char nom_fich_recu[MAX_BUF];
  • // Pour compter les bloques recues
  • int num_bloc = 0;
  • // Fonctions utilise par le client
  • int cree_socket(int);
  • ////////////////////////////////////////////////////////////////
  • // Procedure principale //
  • ///////////////////////////////////////////////////////////////
  • int main(int argc, char **argv)
  • {
  • // Buffer pour la lecture et l'ecriture dans le socket
  • char *buf;
  • int long_buf;
  • //Descripteur du client
  • int client;
  • // Utilise par sendto pour garder la valeur de retour
  • int envoye;
  • // Guarde la valeur de retour de la fonction recvfrom
  • int recue;
  • // Pour la construction de l'adresse du serveur
  • struct sockaddr_in serveur;
  • int long_serveur;
  • // Utilise pour la resolution des non des domaine (DNS)
  • // Conversion entre nom_machine->adresse_ip
  • struct hostent *h;
  • // Variable indiquant qu'on a atteint la fin de fichoer
  • int fin = faux;
  • printf("\n Verfication des arguments de la ligne de commande ... ");
  • if (argc != 3)
  • {
  • printf(" [FAILED]");
  • printf("\n Usage: client nom_serveur num_proto\n");
  • exit(1);
  • }
  • printf(" [OK]");
  • // creation du socket
  • printf(" \n Creation du socket ... ");
  • client = cree_socket(atoi(argv[2]));
  • if(client < 0)
  • {
  • perror("Cause");
  • exit(1);
  • }
  • // Allocation du buffer
  • printf(" \n Allocation du buffer ... ");
  • buf = (char *)malloc(MAX_BUF);
  • if(buf == NULL)
  • {
  • printf(" [FAILED]\n");
  • perror("Cause");
  • exit(1);
  • }
  • printf(" [OK]\n");
  • // Le client envoi une demande de connexion
  • long_buf = strlen("connect");
  • strcpy(buf,"connect");
  • // On construit l'adresse du serveur
  • printf("\n Construction de l'adresse du serveur ... ");
  • serveur.sin_family = AF_INET;
  • serveur.sin_port = htons(SERV_PORT);
  • printf(" [OK]");
  • printf("\n Resolution du nom de serveur %s ... ", argv[1]);
  • h = gethostbyname(argv[1]);
  • if (h == NULL)
  • {
  • printf(" [FAILED]\n");
  • perror("Cause");
  • exit(1);
  • }
  • printf(" [OK]\n");
  • struct in_addr *addr_ip_serv = (struct in_addr *)h->h_addr_list[0];
  • printf("\n Adresse ip du serveur est: %s",
  • inet_ntoa(*addr_ip_serv));
  • memcpy((char*)(&serveur.sin_addr.s_addr), h->h_addr_list[0], h->h_length);
  • long_serveur = sizeof(serveur);
  • // On va envoye une demande de connexion au serveur
  • // notre protocole consiste a envoye un message contenant
  • // la chaine de caractere "connect"
  • // ceci n'est pas necessaire en mode connecte
  • // car c'est la fonction connect qui assure cette tache
  • printf("\n Demande de connexion au serveur ... ");
  • envoye =
  • sendto(client, buf, long_buf , 0,
  • (struct sockaddr *)&serveur,
  • long_serveur);
  • if (envoye < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • // S'il y a une erreur de reception en arrete tout
  • exit(1);
  • }
  • printf(" [OK]");
  • printf("\n Attente de validation ou refus de connexion ... ");
  • memset(buf,0,strlen(buf));
  • recue =
  • recvfrom(client, buf, long_buf, 0,
  • (struct sockaddr *)&serveur,
  • &long_serveur);
  • if (recue < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause:");
  • exit(1);
  • }
  • if(strcmp(buf,"OK") != 0 && strcmp(buf,"NO") != 0)
  • {
  • printf(" [OK] \n");
  • printf("\n Attendu OK ou NO recue %s.\n", buf);
  • exit(1);
  • }
  • if(strcmp(buf,"NO") == 0)
  • {
  • printf(" [FAILED]");
  • printf("\n\t\t !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ");
  • printf("\n\t\t !!! Le serveur est charge !!! ");
  • printf("\n\t\t !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \n");
  • close(client);
  • exit(1);
  • }
  • if(strcmp(buf,"OK") == 0)
  • {
  • printf(" [OK]");
  • printf("\n\t\t ***************************************");
  • printf("\n\t\t *** Le serveur a accepte la demande ***");
  • printf("\n\t\t ***************************************");
  • }
  • // Changement du port du serveur
  • // pour devenir celui du thread associe
  • serveur.sin_port = htons(atoi(argv[2])+1);
  • // On envoi le nom de fichier a cherche
  • printf("\n Entrer le nom de fichier a cherche: ");
  • scanf("%s",buf);
  • long_buf = strlen(buf) + 1;
  • sprintf(nom_fich_recu, "copie_de_%s",buf);
  • printf("\n Envoi du nom de fichier ... ");
  • envoye =
  • sendto(client, buf, long_buf , 0,
  • (struct sockaddr *)&serveur,
  • long_serveur);
  • if(envoye < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • close(client);
  • exit(1);
  • }
  • printf(" [OK]");
  • // On envoi la chaine a recherche dans le fichier
  • printf("\n Entrer le motif a cherche: ");
  • memset(buf,0,strlen(buf));
  • scanf("%s",buf);
  • long_buf = strlen(buf);
  • printf("\n Envoi du motif ... ");
  • envoye =
  • sendto(client, buf, long_buf , 0,
  • (struct sockaddr *)&serveur,
  • long_serveur);
  • if(envoye < 0)
  • {
  • printf(" [FAILED]\n");
  • perror("Cause");
  • close(client);
  • exit(1);
  • }
  • printf(" [OK]");
  • // Reception de la reponse pour l'existence du fichier
  • printf("\n Attente de la reponse d'existance du fichier ...");
  • memset(buf,0,strlen(buf));
  • long_buf = MAX_BUF;
  • recue =
  • recvfrom(client, buf, long_buf, 0,
  • (struct sockaddr *)&serveur,
  • &long_serveur);
  • if (recue < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • close(client);
  • exit(1);
  • }
  • printf(" [OK]");
  • if(!strcmp(buf,"EXIST"))
  • {
  • printf("\n Le serveur a trouve le fichier cherche. \n");
  • }
  • else if(!strcmp(buf,"NO_EXIST"))
  • {
  • printf("\n Le serveur n'a pas reussi a trouve le fichier.\n");
  • close(client);
  • exit(1);
  • }
  • else
  • {
  • printf(" \n Attendu 'EXIST' ou 'NO_EXIST': Recue %s \n",buf);
  • close(client);
  • exit(0);
  • }
  • fd = fopen(nom_fich_recu,"w+");
  • printf("\n **************************************************************** ");
  • printf("\n * Reception du contenu * ");
  • printf("\n **************************************************************** \n");
  • long_buf = MAX_BUF;
  • if(fd == NULL)
  • {
  • printf("\n Impossible de cree un fichier pour la reception des donnees recu");
  • perror("Cause");
  • close(client);
  • exit(1);
  • }
  • else
  • do /* tanque non fin de fichier */
  • {
  • num_bloc ++;
  • do /* Tanque un bloque n'a pas ete recue */
  • {
  • printf("\n - Attente du bloque de donnee N%d... ",num_bloc);
  • // Effacer le contenu du buffer
  • long_buf = MAX_BUF;
  • memset(buf,0,MAX_BUF);
  • recue =
  • recvfrom(client, buf, long_buf, 0,
  • (struct sockaddr *)&serveur,
  • &long_serveur);
  • if(recue < 0)
  • {
  • printf(" [FAILED]\n");
  • printf("\n Erreur lors de la reception des donnees. \n");
  • perror("Cause");
  • strcpy(buf,"NO");
  • long_buf = strlen("NO")+1;
  • printf("\n Envoye une demande de retransmission ... ");
  • envoye =
  • sendto(client, buf, long_buf, 0,
  • (struct sockaddr *)&serveur, long_serveur);
  • if(envoye < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • printf("\n Il y a eu une erreur lors de la reception du bloque ");
  • printf("\n et une erreur lors de la demande de retransmission. ");
  • printf("\n Par consquent le bloque envoye par le serveur est sera perdu. ");
  • break; // Puisque on a pas pu prevenir le serveur qu'il y eu une erreur
  • // on evite le bloque actuel et en previent le client qu'il y a
  • // une perte de donnees
  • }
  • printf(" [OK]");
  • continue;
  • } /* if recue < 0 */
  • printf(" [OK]");
  • break; // Cassage de la boucle de retransmission
  • }while(vrai); /* Reception du bloque */
  • if(!strcmp(buf,"$FIN$") || !strcmp(buf, "$ERREUR$"))
  • fin = vrai;
  • // Ecrire les donnees recu dans le fichier qui porte comme nom
  • // client-num_port
  • if(fin == faux) // Car $FIN$, $ERREUR$ ne font pas partie du fichier transferer
  • if(fprintf(fd,"%s",buf) < 0)
  • {
  • printf("\n Erreur d'ecriture dans le fichier de reception. \n");
  • perror("Cause");
  • exit(1);
  • }
  • // On previent le serveur que le bloque qu'il a envoye
  • // a ete recue avec succe en lui envoyant un OK
  • strcpy(buf,"OK");
  • long_buf = strlen("OK")+1;
  • printf("\n * Envoye un 'OK' au serveur ... ");
  • envoye =
  • sendto(client, buf, long_buf,0,
  • (struct sockaddr *)&serveur, long_serveur);
  • if(envoye < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • continue;
  • }
  • printf(" [OK]");
  • }while(fin == faux); /* !feof(df) */
  • // On attend la reponse concernant le motif //
  • printf("\n Attente de la recpetion concernant le motif ... ");
  • long_buf = MAX_BUF;
  • memset(buf,0,MAX_BUF);
  • recue =
  • recvfrom(client, buf, long_buf, 0,
  • (struct sockaddr *)&serveur,&long_serveur);
  • if(recue < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • }
  • else
  • {
  • printf(" [OK]");
  • printf(" %s",buf);
  • printf("\n Envoye un OK au serveur ... ");
  • strcpy(buf,"OK");
  • long_buf = strlen(buf) +1;
  • envoye =
  • sendto(client, buf, long_buf,0,
  • (struct sockaddr *)&serveur, long_serveur);
  • if(envoye < 0)
  • {
  • printf(" [FAILED]");
  • perror("Cause");
  • }
  • printf(" [OK]");
  • printf(" \n Le transfert est termine avec succe.");
  • printf(" \n Ouvrir le fichier %s pour voir le resultat de la recpetion.",
  • nom_fich_recu);
  • }
  • fclose(fd);
  • close(client);
  • printf("\n");
  • return 0;
  • }
  • //////////////////////////////////////////////////////////////////
  • //Procedure aui permet la creation d'une socket //
  • //Elle attend le numero de port //
  • //et elle nou renvoi un descripteur //
  • //////////////////////////////////////////////////////////////
  • int cree_socket(int port)
  • {
  • struct sockaddr_in serveur_addr;
  • int serveur;
  • // Creation du socket
  • serveur = socket(AF_INET, SOCK_DGRAM, 0);
  • if(serveur < 0)
  • {
  • perror(" [FAILED] \n");
  • return(-1);
  • }
  • printf(" [OK]\n");
  • // La famille a laquelle appartient le socket
  • serveur_addr.sin_family = AF_INET;
  • // Adresse specifique qui permet de dir au systeme
  • // que je suis en ecoute sur tout les adresse IP entrantes
  • serveur_addr.sin_addr.s_addr = htons(INADDR_ANY);
  • // Le port utilise par le socket
  • serveur_addr.sin_port = htons(port);
  • // Attachement du socket au systeme
  • printf("\n Attachement de la socket cree avec le systeme ... ");
  • if(bind(serveur, (struct sockaddr *) &serveur_addr, sizeof(serveur_addr)) < 0)
  • {
  • printf(" [FAILED]\n");
  • perror("Cause");
  • return(-1);
  • }
  • printf(" [OK]");
  • return serveur;
  • }
//////////////////////////////////////////////////////////////////////
//                          Code du serveur                         //
//////////////////////////////////////////////////////////////////////

/***************************************************************************/
/* 					El Antri Abdellah 	           */
/*           			Sous licence GNU			   */
/***************************************************************************/

/**************************************************************************/
/*				Rmarque importante			  */
/* Le serveur créé des fichiers log pour chaque client et un historique   */
/* des connexions directement dans la racine / par consequent il faut     */
/* ilo faut avoir les privileges root                                     */
/**************************************************************************/

/* Marche sous linux/unix */
/* Compilation: cc fudps.c -o serveur -lpthreqd */
/* Execution: ./serveur 1200                    */

#include <time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>            
#include <sys/stat.h>           
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>             
#include <unistd.h>           
#include <stdio.h>              

#define vrai 1
#define faux 0

// Cette constante permet de specifie la longueur
// maximal d'un chemin specifiant un repertoire
#define MAX_REP_CHEMIN 2048

// Cette constante desgine le nombre de thread autorise a cree
#define MAX_THREAD 4

// Ddefinie la long maximal du buffer
#define MAX_BUF 2048 


// Declaraation des variables globales utilise
int num_libre;

// Tableau d'identificateur
pthread_t th_id[MAX_THREAD];

// Tableau pour indique les identificateur deja pris
int th_occupe [MAX_THREAD];

// Fichier contenant l'historique des connexions et des dmandes de connexion
FILE *hist;

// Declaration des fonctions et procedures 
// utiliser par notre serveur

void section_critique(FILE *);
int cree_socket(int, FILE * );
char * cherche_fichier(char *, FILE *);
void * th_trait(void  *);


// Procedure principale 
int main (int argc , char ** argv)
{
// Descripteur du serveur 
int serveur;

// Adresse du client
// Utilise par recvfrom pour recevoir les
// informations du client qui a envoye une 
// demande de connexion

struct sockaddr_in client;

// Longueur de la structure utilise par client
int long_client;

// Pour le parcour du tabbleau des identificateurs des thread
int i; 

// utilise pour guarder la Valeur de retour de recvfrom
int recue;

// Utiliser pour guarder la valeur de retour de sendto
int envoye;

// Utilise pour la lecture de la demande de connexion
char *buf;
int long_buf;

// Pour lire la date
time_t temp;
// Contient le chemin du fichier historique
char nom_hist[MAX_REP_CHEMIN + 1];


system("clear");
printf("\n Arguments de la ligne de commande ... ");

if (argc != 2)
   {
   printf(" [FAILED]");
   printf("\n Usage: serveur num_proto\n");
   exit(1);
   }
printf(" [OK]");

strcpy(nom_hist, "/historique");
printf("\n Creation du fichier %s ... ",nom_hist);
hist = fopen(nom_hist,"w+");
if(hist == NULL)
  {
  printf(" [FAILED]\n");	  
  perror("Cause");
  exit(1);
  }	  
printf(" [OK]\n");	  

time(&temp);
fprintf(hist," -------------------------------------------------\n");
fprintf(hist,"| Ce fichier contient l'historique des connexions |\n");
fprintf(hist," -------------------------------------------------\n");

fprintf(hist," Date de creation: %s \n ", ctime(&temp) );

// Initialisation du buffer
// On va essayer d'alloue MAX_BUF octet

printf("\n Allocation du buffer ... ");
fprintf(hist, "\n Allocation du buffer ... ");
buf = (char *)malloc(MAX_BUF);
if(buf == NULL)
  {
  printf("\n Impossible d'alloue de l'espace pour le buffer");
  // Sans le buffer on ne peut rien faire
  exit(1);
  }
printf(" [OK]");
fprintf(hist, " [OK]");
       
// Initialisation du tableau des threads
printf("\n Initialisation du tableau d'id de thread ... ");
fprintf(hist, "\n Initialisation du tableau d'id de thread ... ");
for (i = 0; i < 4; i++)
   {
   th_occupe[i] = -1;
   }
printf(" [OK]");
fprintf(hist, " [OK]");

// Initialisation num_libre a 0
num_libre = 0;

// creation du socket
fprintf(hist, "\n Creation de socket sur le port %d... ",atoi(argv[1]));
printf("\n Creation de socket sur le port %d... ",atoi(argv[1]));
serveur = cree_socket(atoi(argv[1]),hist);
if(serveur == -1)
  {
  printf("\n Un probleme a interrompu la creation du socket.\n");
  exit(1);
  }

printf("\n \t  Le serveur va entre dans une boucle infini  \n");
printf("   \t  =========================================   ");

      ////////////////////////////////////////////////////////////
      //         Boucle de gestion des connexions               //
      ///////////////////////////////////////////////////////////

while(vrai)
{
fflush(stdout);//vidage de la sortie standard

printf("\n \t **************************************************");
printf("\n \t ***     Attente des demandes de connexion      ***");
printf("\n \t **************************************************");
printf("\n");
// Le serveur attend une demande de connexion 
fprintf(hist, "\n Attente de demande de connexion ... ");
long_buf = strlen("connect"); 
recue = 
       recvfrom(serveur, buf, long_buf , 0, 
		(struct sockaddr*)&client, &long_client);
    
if (recue < 0)
   {
   fprintf(hist, " [FAILED]\n");
   perror("Cause");
   // S'il y a une erreur de reception en arrete tout
   exit(1);
   }    
fprintf(hist, " [OK]");   

// On doit recupere les informations du client
// qui a demande une connexion
printf("\n %s:%u demande la connexion au serveur ...", 
	inet_ntoa(client.sin_addr),ntohs(client.sin_port));
time(&temp);
fprintf(hist, "\n  Une demande de connexion est recue:\n");
fprintf(hist, "  _==================================_\n");
fprintf(hist, "\t * Date de connexion:  %s", ctime(&temp));
fprintf(hist, "\t * Famille du Socket client: %x\n", ntohs(client.sin_family));
fprintf(hist, "\t * Port client: %u\n", ntohs(client.sin_port));
fprintf(hist, "\t * IP client:  %s\n", inet_ntoa(client.sin_addr));

if(strcmp(buf,"connect") == 0)
   {
   fprintf(hist, "\n Le client a envoye %s.", buf);	   
   fprintf(hist, " ...  Requete valide");
   }
   else
       {
       fprintf(hist, "\n Requete inconnu: Attendu  connect recue %s", buf);
       continue ;
       }

// Validation de la demande par un OK
// Ceci n'est pas necessaire en mode connecte
// car c'est la commande accepte qui realise cette tache
fprintf(hist, 
	    "\n Le serveur envoi une reponse au %s:%u ...",
	     inet_ntoa(client.sin_addr),ntohs(client.sin_port));
long_client = sizeof(client);

if(num_libre > 3)
   {
   strcpy(buf,"NO");
   long_buf = strlen("NO") + 1;
   envoye =
            sendto(serveur,buf,long_buf,0,
	    (struct sockaddr *)&client,
            long_client);
   if(envoye < 0)
     {
      fprintf(hist, " [FAILED]\n");
      perror("Cause");
      continue ;
      }
   printf("\n Connexion du %s:%u refuse: depacement de capacite \n",
                 inet_ntoa(client.sin_addr),ntohs(client.sin_port));
   fprintf(hist, " [OK]\n");
   fprintf(hist,"\n|**************************************************|");
   fprintf(hist,"\n DEPACEMENT DE  CAPACITE  DU SERVEUR       "); 
   fprintf(hist, "\n Connexion du client %s:%u refuse       ", 
          inet_ntoa(client.sin_addr),
	  ntohs(client.sin_port));
   fprintf(hist,"\n|**************************************************|");
   } 
    else
        {
        strcpy(buf,"OK");
        long_buf = strlen("OK") + 1;
        envoye =
                 sendto(serveur,buf,long_buf,0,
	         (struct sockaddr *)&client,
                 long_client);
        if(envoye < 0)
          {
           fprintf(hist," [FAILED]\n");
           perror("Cause");
           continue;
          }
        fprintf(hist, " [OK]\n");
        num_libre ++;

	// On cherche un identificateur libre
        for(i = 0; i < 4; i++)
	    if(th_occupe[i]  == -1)
	       {
	        // La structure special contient le nom de fichier
		// la chaine a recherche
		// et l'adresse du client
		// creation du thread associe au client
		fprintf(hist, "\n Creation de thread ... ");
                if(
		   pthread_create(&th_id[i], 
                		    NULL,(void *) th_trait, 
	                 	     (void *)&client)  != 0
		   )
		   {
		   fprintf(hist, " [FAILED]\n");
		   exit(1);
		   }
	       th_occupe[i] = th_id[i];   
               break;
               }
        } 
 freopen(nom_hist,"a+",hist);	
 }// while(true)

}

// Thread  dedie  pour la recherche de fichier
// Et la recherche des motifs dans un fichier

void * th_trait(void *client_addr)
{
 
// Descripteur de fichier 
// utilise par fopen pour la lecture de fichier
// cherche dans le cas ou il existe

FILE *df;

// Descripteur de fichier log pour chaque thread
FILE *log;
char nom_log[MAX_BUF];

// Descripteur du socket serveur
// car chaque thread va avoir un numero de port
// speciale pour communiquer avec sont client
// ceci n'est pas necessaire dans le mode connecte
// puisque accepet retourne un identificateur nouveau
// pour chaque demande de connexion

int serveur;

// longuer de la structure sockaddr client
int long_client;

// utilise pour recuperer les valeurs de retour
// des fonctions recvfrom et sendto
int envoye, recue;

// Tampon de lecture ecriture
char *buf;

// Pour specifie la longueur du bufer
int long_buf;

// Stocke le nom de fichier envoye par le client
char nom_fichier[MAX_REP_CHEMIN];

// Stocke le chemin d'acce au fichier
// retourne par la fonction recherche_fichier
char chemin[MAX_REP_CHEMIN];

// Stocke la chaine a cherche dans le fichier
char motif[MAX_BUF];
// ndice indiquant si le motif a ete trouve ou pas
int motif_trouve = -1;

// Pour le parcour du tableau de thread
int i;

// Pour compter le nombre des bloque envoye au client;
int num_bloc = 0;

// Utilise pour savoir la longueur lu par la fct read
int long_lu=0;
 
struct sockaddr_in *client = (struct sockaddr_in *)client_addr; 

// Pour obtenir le repertoire courant du travail
char rtc[MAX_REP_CHEMIN];

// Creation de thread reussi


sprintf(nom_log,"/serveur%s:%u.log", 
       inet_ntoa(client->sin_addr),ntohs(client->sin_port));
printf("\n -> Pour les details de transfert voir le fichier: %s", nom_log);

log = fopen(nom_log ,"w+");
if(log == NULL)
   {
   printf("\n Erreur d'ouverture du fichier log.\n");
   perror("Cause");
   pthread_exit(1);
   }

fprintf(log," -----------------------------------------------------\n");
fprintf(log,"| Fichier log generer automatiquement par le serveur |");
fprintf(log,"\n -----------------------------------------------------\n");

fprintf(log, "\n Le thread %d va s'occupe de la demande du client  %s\n",
       pthread_self(),inet_ntoa(client->sin_addr));

// Essayer d'allouer le buffer
buf = (char *)malloc(MAX_BUF); 
if (buf == NULL)
    {
    fprintf(log,"\n Impossible d'alloue le buffer.\n", 
           pthread_self());
    fprintf
	  (log, "\n Arret du trait associe su client %s:%u \n",
          inet_ntoa(client->sin_addr),
	  ntohs(client->sin_port)
	  );
    fclose(log);
    section_critique(log);
    pthread_exit(1);
    }
 
long_buf = MAX_BUF; 
long_client = sizeof(client);

// Creation de socket pour le thread
fprintf(log, " Creation de socket ... ",pthread_self());

// Creation d'un nouveau socket pour chaque thread
// avec un numero de port = num_port_client + 1

serveur = cree_socket(ntohs(client->sin_port)+1, log);
if(serveur < 0)
  {
   fclose(log);
   section_critique(log);
   pthread_exit(1);
  }

// Attente de messages des clients
// On attend un nom de fichier a cherhe 
fprintf(log, "\n Attente du nom de fichier a cherche ... ",
        pthread_self()); 
memset(buf,0,strlen(buf));
recue = 
        recvfrom(
		serveur, buf, long_buf , 0, 
		(struct sockaddr*)client, &long_client
		);
if (recue < 0)
    {
      fprintf(log, " [FAILED]");
      perror("Cause");
      fclose(log);
      close(serveur);
      section_critique(log);
      pthread_exit(1);
    }
  
fprintf(log, " [OK]");
strcpy(nom_fichier,buf);
fprintf(log, "\n Le fichier cherche est: %s", nom_fichier);

// On attend la motif a cherche dans le fichier

 fprintf(log, "\n Attente du motif a cherche ... ",pthread_self());
 memset(buf,0,strlen(buf));
 recue = 
	 recvfrom(
		serveur, buf, long_buf , 0, 
		(struct sockaddr*)client, &long_client
		);
 if (recue < 0)
    {
      fprintf(log," [FAILED]\n");
      perror("Cause");
      fclose(log);
      close(serveur);
      section_critique(log);
      pthread_exit(1);
    }
 strcpy(motif, buf);
 fprintf(log, " [OK]"); 
 fprintf(log, " \n Le motif cherche est: %s", motif); 

// Recherche du fichier et recuperation de sont chemin
// dans le cas ou il existe

 fprintf(log, "\n Recherche du fichier %s ... ",nom_fichier);
 
 memset(chemin,0,strlen(chemin));
 
 strcpy(chemin,cherche_fichier(nom_fichier,log));


 if(!strcmp(chemin,"NO_EXIST"))
   {
   fprintf(log, "\n Le fichier cherche n'existe pas ...  ");
   // On envoi un message pour prevenir le client
   // que le fichier qu'il a demande n'existe pas
   // dans le serveur
   fprintf(log, "\n Envoyer  'NO_EXIST' au client ... ");
   strcpy(buf,"NO_EXIST");
   long_buf = strlen("NO_EXIST") + 1;
   envoye =
           sendto(serveur,buf,long_buf,0,
           (struct sockaddr *)client,
            long_client);
    if(envoye < 0)
       {
       fprintf(log," [FAILED]");
       perror("Cause");
       }
  fprintf(log," [OK]");
  close(serveur);
  fclose(log);
  section_critique(log);
  pthread_exit(1);
  }	


// Si on est arrive ici, ca veut dir que le fichier existe
fprintf(log,"\n Le fichier existe et sont chemin est: %s\n",chemin);
printf("\n Le fichier existe et sont chemin est: %s\n",chemin);

fprintf(log, "\n Envoyer 'EXIST' au client ... ");
strcpy(buf,"EXIST");
long_buf = strlen("EXIST") + 1;

envoye =
         sendto(serveur,buf,long_buf,0,
         (struct sockaddr *)client,
          long_client);

if(envoye < 0)
  {
  perror("Cause");
  close(serveur);
  fclose(log);
  section_critique(log);
  pthread_exit(1);
  }

// On ouvre le fichier pour lecture 
// la fonction fopen nous retourne un descripteur 
// qui va etre utilise par la fonction fscanf;
fprintf(log, "\n Debut de transfert:");
fprintf(log, "\n ___________________");
df = fopen(chemin,"r+");

if(df != NULL)
  {

   // Tanque fin de fichier non atteinte on envoi un bloque de donne de taille
   // strlen(buf) au client qui possede l'adresse client
   while(!feof(df))
      {
      num_bloc ++; 
      if((long_lu = fread(buf,1,MAX_BUF,df)) < 0)
         {
         fprintf(log, "\n Erreur de lecture de fichier.\n");
         perror("Cause");
         break;         
         }
      buf[long_lu] = '\0';
      // La recherche du motif dans le buffer courant
      if(strstr(buf, motif))
	 {
	 motif_trouve = num_bloc;	 
	 }
      fprintf(log,"\n Lecture d'un bloque avec succe.");
      do
       {
        fprintf(log,
              "\n\t Envoi du bloc N %d ",num_bloc);
	long_buf = strlen(buf)+1;
        envoye = 
 	      sendto(
	 	   serveur,buf, long_buf, 0, 
	           (struct sockaddr *)client, long_client
		   );
        if(envoye < 0)
           {
           fprintf(log, "\n Erreur d'envoi de donne. \n");
           perror("Cause");
           continue;
           }
       fprintf(log,"\n\t Les donnees on ete envoyees avec succe.");
       fprintf(log, "\n Attente de validation par le client ... ");
       memset(buf,0,strlen(buf));
       recue = 
            recvfrom(serveur, buf, long_buf,0,
                      (struct sockaddr *)client, &long_client);
       if(recue < 0)
         {
         fprintf(log," [FAILED]");
         continue;
         }
       fprintf(log," [OK]");
       if (!strcmp(buf,"OK"))
          {
          fprintf(log, 
           "\n Le bloque N %d a ete recue par le client avec succe.",num_bloc);
          break;
          }
          else if(!strcmp(buf,"NO"))
              {
              fprintf(log,
                     "\n Le client a demande la retransmission du bloc N %d",
                     num_bloc);
              continue;
              }
        }while (vrai);   /* do  d'envoi de bloc*/

     }                 /* while(!feof(df))*/  
  }                    /*if(df != NULL)*/

   else 
        {
        fprintf(log, 
              "\n Un probleme est survennu lors de l'ouverture du fichier.");
        perror("Cause");
        strcpy(buf,"$ERREUR$");
        long_buf = strlen(buf);
        sendto(serveur, (char *) buf, long_buf, 0,
               (struct sockaddr *)client, long_client);       
        fclose(log);
        close(serveur);
        section_critique(log);
        pthread_exit(1);
        }

strcpy(buf, "$FIN$");
long_buf = strlen(buf) + 1;
fprintf(log,"\n Envoye $FIN$ au client %s:%u ... ", inet_ntoa(client->sin_addr),
		ntohs(client->sin_port));
envoye =
          sendto(serveur, (char *) buf, long_buf, 0,
          (struct sockaddr *)client, long_client);       
if(envoye < 0)
  {
  printf(" [FAILED]");
  fprintf(log, " [FAILED]");
  perror("CAUSE");
  }
  else 
    {
    fprintf(log, " [OK]");
    printf("\n Envoi du fichier a ete termine avec succe");
    fprintf(log, "\n\t\t  ------------------------  ");
    fprintf(log, "\n\t\t |Envoi du fichier termine| ");
    fprintf(log, "\n\t\t  ------------------------  ");

    fprintf(log,"\n Envoyer la reponse indiquant si le motif a ete trouve ...");
    if(motif_trouve >= 0)
     {
     memset(buf,0,MAX_BUF);
     // Le serveur renvoi une reponse indiquant le numero de bloque
     // qui contient la premiere occurence du motif cherche
     sprintf(buf,"\n Le motif cherche existe dans le bloc %d:",motif_trouve);
     long_buf = strlen(buf) + 1;
     }
      else 
          {
          sprintf(buf,"\n Le motif cherche n'existe pas dans le fichier.");
          long_buf = strlen(buf) + 1;
          long_buf = strlen("\n Le motif n'existe pas dans le fichier.") + 1;
          }
     envoye =
	      sendto(serveur, (char *) buf, long_buf, 0,
               (struct sockaddr *)client, long_client);       
     if(envoye < 0)
	{
	fprintf(log, " [FAILED]");
	}
        else
	     {	
              fprintf(log, " [OK]");	      
	      fprintf(log,"%s",buf); // Le motif existe ou n'existe pas
	      fprintf(log, " \n Reponse concernant le motif ... ");
              recue =
                      recvfrom(serveur, (char *) buf, long_buf, 0,
                      (struct sockaddr *)client, &long_client);       
               if(recue < 0)
                 {
	          fprintf(log, " [FAILED]");
                  perror("CAUSE");	
	           }
                  else
	             {
                      fprintf(log, " [OK]");
	              printf(
		      "\n La requete du client %s:%u a ete traite avec succe.",                            inet_ntoa(client->sin_addr),
			    ntohs(client->sin_port));
                      fprintf(log,
   		    "\n La requete du client %s:%u a ete traite avec succe.", 
                              inet_ntoa(client->sin_addr),
			      ntohs(client->sin_port));
	             }
             }
     }
fclose(log);
fclose(df);
close(serveur);
section_critique(log);

return NULL;
}


///////////////////////////////////////////////////////////////////////////
// Cette procedure permet de liberer un identificateur de decrementer   //
// le nombre de clients qui se trouve dans le serveur                   //
/////////////////////////////////////////////////////////////////////////

void section_critique(FILE *log)               
{
int i;
pthread_mutex_t mut;

// Initialisation du verrou
// Cette fonction retourne toujour 0
fprintf(log, "\n Initialisation du verrou ... ");  
pthread_mutex_init(&mut, NULL);
fprintf(log, " [OK]\n");


// Section critique
fprintf(log, "\n Debut de la section critique ... ");  
pthread_mutex_lock(&mut);
// Decrement le nombre de client
num_libre --;
// libere l'identificateur de thread
for(i = 0; i < 4; i ++)
   if(th_occupe[i] == pthread_self())
     th_occupe[i] = -1;
pthread_mutex_unlock(&mut);       
fprintf(log, "\n Fin de la section critique ... ");  
// Fin de la section critique
}

///////////////////////////////////////////////////////////////////////////
// Cette fonction permet de cree un Socket                               //
// Ca valeur de retour est un descripteur dans la table des descripteur  //
// du processus c'est pour cela qu'il faut un bind pour quelle soit     //
// definie aupres du systeme                                            // 
/////////////////////////////////////////////////////////////////////////


int cree_socket(int port, FILE *hist)
{

  struct sockaddr_in serveur_addr;
  int serveur;
  
  // Creation du socket
  serveur = socket(AF_INET, SOCK_DGRAM,0);
  if(serveur < 0)
    {
      printf(" [FAILED]");
      perror("Cause");
      return -1;
    }
  fprintf(hist, " [OK]");
  // La famille a laquelle appartient le socket
  serveur_addr.sin_family = AF_INET;
  
  // Adresse specifique qui permet de dir au systeme
  // que je suis en ecoute sur tout les adresse IP entrantes
  serveur_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  
  // Le port utilise par le socket
  serveur_addr.sin_port = htons(port);
 
 fprintf(hist, "\n Attachement du socket avec une adresse ip/port ... ");
 // Attachement du socket au systeme
  if(bind(serveur, (struct sockaddr *) &serveur_addr, sizeof(serveur_addr)) < 0)
    {
      fprintf(hist, " [FAILED]");
      perror("Cause");
      return -1;
    }
  fprintf(hist, " [OK]\n"); 
  return serveur;
}

///////////////////////////////////////////////////////////////////////////
// Cette fonction permet de cherche un fichier                           //
// dans l'arborescence du systemes et de voir si ce fichier              //
// contient la chaine recherche                                          //
///////////////////////////////////////////////////////////////////////////

char * cherche_fichier(char *nom, FILE * log)
{

    static int trouve = faux;

    // Pointeur sur descripteur de repertoire          
    DIR* rep;                            

    // Pointeur sur une entree repertoire              
    struct dirent* entree; 

    // Repertoire de travail courant                  
    char rtc[MAX_REP_CHEMIN + 1], sauv[MAX_REP_CHEMIN + 1];
    //Chemin complet de notre fichier
    static char chemin[MAX_REP_CHEMIN + 1];

    // Utilise par stat() pour teste le type des entree   
    struct stat rep_stat;                

     char pile[MAX_REP_CHEMIN][MAX_REP_CHEMIN];
     int som = 0;
     

strcpy(pile[som],"/");
som++;
do {
   som --;
   strcpy(sauv,pile[som]);
   if  (chdir(sauv) == -1)
    {
    fprintf(log, "\n %s",sauv);
    fprintf(log," \n Erreur lors du changement de repertoire ...");
    strcpy(chemin,"NO_EXIST");
    return chemin;
    }
      
   fprintf(log, "\n Recherche dans %s: ", sauv);
   
   // ouvrir le repertoir pour lecture 
   rep = opendir(".");
   if (!rep) 
        {
	fprintf(log, "\n Impossible de lire le repertoire %s.\n ", sauv);
	perror("Cause");
	strcpy(chemin,"NO_EXIST");
	return chemin;
        } 

    ///////////////////////////////////////////////////////////////////////
    //  Parcour du repertoire courant ainsi que tout les sous repertoire //
    ///////////////////////////////////////////////////////////////////////    

    do
    {
     entree = readdir(rep);
     if(entree == NULL)
       {
       fprintf(log, "\n Le parcour de %s est termine.\n",sauv);
       break;
       }  

     if(entree != NULL)
        {
        fprintf(log, "\n Entree courante est: %s", entree->d_name);
	
	if ( entree->d_name && !strcmp(entree->d_name,nom)) 
            {
            if (getcwd(rtc, MAX_REP_CHEMIN) == NULL) 
                {
	         perror("Cause");
	         strcpy(chemin,"NO_EXIST");
	         return chemin;
                 }
	    if(strcmp(rtc,"/"))
	        strcat(rtc,"/"); 
	    strcat(rtc,entree->d_name);
	    strcpy(chemin,rtc);
	    // retourne le chemin d'acce complet du fichier 
             fprintf(log, "\n Le chemin du fichier cherche est: %s\n",
                 chemin);
 	     return chemin;
	    }
        
        // on evite les repertoires systemes
        // si vous voulez effectue une recherche dans ses repertoires
        // il faut les supprimes, mais le temps de recherche augmentera
        // considerablement
        if(strcmp(entree->d_name,"Recycled") == 0)
            continue;
        if(strcmp(entree->d_name,"dev") == 0)
            continue;
        if(strcmp(entree->d_name,"proc") == 0)
            continue;
        if(strcmp(entree->d_name,"root") == 0)
            continue;
        if(strcmp(entree->d_name,"mnt") == 0)
            continue;
        if(strcmp(entree->d_name,"lib") == 0)
            continue;
        if(strcmp(entree->d_name,"usr") == 0)
            continue;
        if(strcmp(entree->d_name,"etc") == 0)
            continue;
	if (strcmp(entree->d_name, ".") == 0)
	    continue;
	if (strcmp(entree->d_name, "..") == 0)
	    continue;

        if(entree->d_name != NULL)
          if ( stat(entree->d_name, &rep_stat) == -1)
             {
             continue;
             }
	// On teste si l'entre courante est un repertoir
        if (S_ISDIR(rep_stat.st_mode))
           {
	    if(som < MAX_REP_CHEMIN )
	        {
                if (getcwd(rtc, MAX_REP_CHEMIN) == NULL) 
                   {
	           perror("Cause");
	           strcpy(chemin,"NO_EXIST");
	           return chemin;
                   }
		if(strcmp(rtc,"/"))
		   strcat(rtc,"/"); 
		strcat(rtc,entree->d_name);
		if(strcmp(rtc, sauv) != 0) // Eviter les autoreferences
		  {
	   	  strcpy(pile[som],rtc);
	          som++;
		  }
	        }
	        else
		   {
		   fprintf(log, "\n Pile pleine ... arret de recherche.");
                   strcpy(chemin,"NO_EXIST");
	           return chemin;
		   }
         } // if (S_DIR)
       } // if(entree =! null )
    }while(vrai); 
  closedir(rep);
  }while(som > 0);

strcpy(chemin,"NO_EXIST");
return chemin;
}


















//////////////////////////////////////////////////////////////////////
//                          Code du client                         //
//////////////////////////////////////////////////////////////////////


/***************************************************************************/
/* 					El Antri Abdellah 		   */
/*           			Sous licence GNU			   */
/***************************************************************************/

/* Pour la plate formae unix/linux    		    */
/* Compilation: cc fudpc.c -o client  		    */
/* Execution: ./client adresse_serveur num_protocol */


#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <dirent.h>            
#include <sys/stat.h>           
#include <string.h>             
#include <unistd.h>           
#include <stdio.h>              

#define vrai 1
#define faux 0

// Numero du port du serveur
#define SERV_PORT 1200

// taille maximal du buffer
#define MAX_BUF 2048

// Descripteur du fichier cree pour la reception
FILE *fd;

// Le nom sous lequel le fichier transferer sera garder
char nom_fich_recu[MAX_BUF];

// Pour compter les bloques recues
int num_bloc = 0;

// Fonctions utilise par le client
int cree_socket(int);


////////////////////////////////////////////////////////////////
//                 Procedure principale                       //
///////////////////////////////////////////////////////////////

int main(int argc, char **argv)
{
// Buffer pour la lecture et l'ecriture dans le socket
char *buf;
int long_buf;

//Descripteur du client
int client;

// Utilise par sendto pour garder la valeur de retour
int envoye;

// Guarde la valeur de retour de la fonction recvfrom
int recue;

// Pour la construction de l'adresse du serveur
struct sockaddr_in serveur;
int long_serveur;

// Utilise pour la resolution des non des domaine (DNS)
// Conversion entre nom_machine->adresse_ip
struct hostent *h;

// Variable indiquant qu'on a atteint la fin de fichoer
int fin = faux;

printf("\n Verfication des arguments de la ligne de commande ... ");
if (argc != 3)
   {
   printf(" [FAILED]");
   printf("\n Usage:  client nom_serveur num_proto\n");
   exit(1);
   }
printf(" [OK]");   

// creation du socket
printf(" \n Creation du socket ... ");
client = cree_socket(atoi(argv[2]));
if(client < 0)
 {
  perror("Cause");
  exit(1);
 }

// Allocation du buffer
printf(" \n Allocation du buffer ... ");
buf = (char *)malloc(MAX_BUF);
if(buf == NULL)
  {
  printf(" [FAILED]\n");  
  perror("Cause");
  exit(1);
  }	
printf(" [OK]\n");

// Le client envoi une demande de connexion 
long_buf = strlen("connect"); 

strcpy(buf,"connect");

// On construit l'adresse du serveur
printf("\n Construction de l'adresse du serveur ... ");

serveur.sin_family = AF_INET;
serveur.sin_port = htons(SERV_PORT);
printf(" [OK]");
printf("\n Resolution du nom de serveur %s ... ", argv[1]);
h = gethostbyname(argv[1]);
if (h == NULL)
    {
    printf(" [FAILED]\n");
    perror("Cause");
    exit(1);
    }
printf(" [OK]\n");

struct in_addr *addr_ip_serv = (struct in_addr *)h->h_addr_list[0];

printf("\n Adresse ip du serveur est: %s", 
	inet_ntoa(*addr_ip_serv));

memcpy((char*)(&serveur.sin_addr.s_addr), h->h_addr_list[0], h->h_length);
long_serveur = sizeof(serveur);

// On va envoye une demande de connexion au serveur
// notre protocole consiste a envoye un message contenant
// la chaine de caractere "connect"
// ceci n'est pas necessaire en mode connecte
// car c'est la fonction connect qui assure cette tache
 
printf("\n Demande de connexion au serveur ... ");
envoye =
       	sendto(client, buf, long_buf , 0, 
		(struct sockaddr *)&serveur,
		long_serveur);
if (envoye < 0)
   {
   printf(" [FAILED]");
   perror("Cause");
   // S'il y a une erreur de reception en arrete tout
   exit(1);
   }
printf(" [OK]");   
printf("\n Attente de validation  ou refus de connexion ... ");

memset(buf,0,strlen(buf));
recue = 
	recvfrom(client, buf, long_buf, 0, 
		(struct sockaddr *)&serveur,
		&long_serveur);
if (recue < 0)
   {
   printf(" [FAILED]");
   perror("Cause:");
   exit(1); 
   }   
if(strcmp(buf,"OK") != 0 && strcmp(buf,"NO") != 0)
  {
  printf(" [OK] \n");
  printf("\n Attendu OK ou NO recue %s.\n", buf);
  exit(1);
  }

if(strcmp(buf,"NO") == 0)
  {
  printf(" [FAILED]");
  printf("\n\t\t !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   ");   
  printf("\n\t\t !!! Le serveur est charge  !!!   ");   
  printf("\n\t\t !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \n");   
  close(client);
  exit(1);
  }
if(strcmp(buf,"OK") == 0)
  {
  printf(" [OK]");
  printf("\n\t\t ***************************************");   
  printf("\n\t\t *** Le serveur a accepte la demande ***");   
  printf("\n\t\t ***************************************");   
  }

// Changement du port du serveur
// pour devenir celui du thread associe 

serveur.sin_port = htons(atoi(argv[2])+1);

// On envoi le nom de fichier a cherche 
printf("\n Entrer le nom de fichier a cherche: ");
scanf("%s",buf);
long_buf = strlen(buf) + 1;

sprintf(nom_fich_recu, "copie_de_%s",buf);

printf("\n Envoi du nom de fichier ... "); 
envoye =
       	sendto(client, buf, long_buf , 0, 
		(struct sockaddr *)&serveur,
		long_serveur);
 
if(envoye < 0)
   {
   printf(" [FAILED]");
   perror("Cause");
   close(client);
   exit(1);
   }	
printf(" [OK]"); 


// On envoi la chaine a recherche  dans le fichier  

printf("\n Entrer le motif a cherche: ");
memset(buf,0,strlen(buf));
scanf("%s",buf);
long_buf = strlen(buf);
printf("\n Envoi du motif ... "); 
envoye =
       	sendto(client, buf, long_buf , 0, 
		(struct sockaddr *)&serveur,
		long_serveur);
 
if(envoye < 0)
   {
   printf(" [FAILED]\n");
   perror("Cause");
   close(client);
   exit(1);
   }	
printf(" [OK]"); 

// Reception de la reponse pour l'existence du fichier
printf("\n Attente de la reponse d'existance du fichier ...");
memset(buf,0,strlen(buf));
long_buf = MAX_BUF;
recue = 
	recvfrom(client, buf, long_buf, 0, 
		(struct sockaddr *)&serveur,
		&long_serveur);
if (recue < 0)
   {
   printf(" [FAILED]");
   perror("Cause");
   close(client);
   exit(1); 
   }   
printf(" [OK]");
if(!strcmp(buf,"EXIST"))
  {
  printf("\n Le serveur a trouve le fichier cherche. \n");  
  }
  else if(!strcmp(buf,"NO_EXIST"))
     {
     printf("\n Le serveur n'a pas reussi a trouve le fichier.\n");
     close(client);
     exit(1);
     }
    else
       {
       printf(" \n Attendu 'EXIST' ou 'NO_EXIST': Recue %s \n",buf);
       close(client);
       exit(0);
       }


fd = fopen(nom_fich_recu,"w+");
printf("\n ****************************************************************   ");
printf("\n *                     Reception du contenu                     *   ");
printf("\n **************************************************************** \n");
long_buf = MAX_BUF;
if(fd == NULL)
  {
  printf("\n Impossible de cree un fichier pour la reception des donnees recu");
  perror("Cause");
  close(client);
  exit(1);
  }
else 
  do /* tanque non fin de fichier */
    {
    num_bloc ++;
    do /* Tanque un bloque n'a pas ete recue */
     {
     printf("\n - Attente du bloque de donnee N%d... ",num_bloc);
    // Effacer le contenu du buffer
    long_buf = MAX_BUF;
    memset(buf,0,MAX_BUF);
    recue = 
	recvfrom(client, buf, long_buf, 0, 
		(struct sockaddr *)&serveur,
		&long_serveur);
    if(recue < 0)
      {
       printf(" [FAILED]\n");
       printf("\n Erreur lors de la reception des donnees. \n");
       perror("Cause");
       strcpy(buf,"NO");
       long_buf = strlen("NO")+1;
       printf("\n Envoye une demande de retransmission ... ");
       envoye = 
	       sendto(client, buf, long_buf, 0, 
               (struct sockaddr *)&serveur, long_serveur);
        if(envoye < 0)
           {
           printf(" [FAILED]");
           perror("Cause");
	   printf("\n Il y a eu une erreur lors de la reception du bloque ");
	   printf("\n et une erreur lors de la demande de retransmission. ");
	   printf("\n Par consquent le bloque envoye par le serveur est sera perdu. ");
	   break;  // Puisque on a pas pu prevenir le serveur qu'il y eu une erreur
	           // on evite le bloque actuel et en previent le client qu'il y a
		   // une perte de donnees
           }
	
        printf(" [OK]");
        continue;
       } /* if recue < 0 */

    printf(" [OK]");
    break; // Cassage de la boucle de retransmission

    }while(vrai); /* Reception du bloque */
    
    if(!strcmp(buf,"$FIN$")  || !strcmp(buf, "$ERREUR$"))
       fin = vrai;
    
    // Ecrire les donnees recu dans le fichier qui porte comme nom
    // client-num_port
    
    if(fin == faux) // Car $FIN$, $ERREUR$ ne font pas partie du fichier transferer
    if(fprintf(fd,"%s",buf) < 0)
        {
         printf("\n Erreur d'ecriture dans le fichier de reception. \n");
         perror("Cause");
         exit(1);
        }
    
    // On previent le serveur que le bloque qu'il a envoye
    // a ete recue avec succe en lui envoyant un OK
    strcpy(buf,"OK");
    long_buf = strlen("OK")+1;
    printf("\n * Envoye un 'OK' au serveur ... "); 
    envoye = 
	    sendto(client, buf, long_buf,0,
                    (struct sockaddr *)&serveur, long_serveur);
    if(envoye < 0) 
      {
       printf(" [FAILED]");
       perror("Cause");
       continue;
      }
    printf(" [OK]");
  
    }while(fin == faux);  /* !feof(df) */     

// On attend la reponse concernant le motif //
printf("\n Attente de la recpetion concernant le motif ... ");
long_buf = MAX_BUF;
memset(buf,0,MAX_BUF);
recue = 
	recvfrom(client, buf, long_buf, 0, 
	(struct sockaddr *)&serveur,&long_serveur);
if(recue < 0)
  {
  printf(" [FAILED]");	  
  perror("Cause");
  }	  
  else
     {
      printf(" [OK]");
      printf(" %s",buf);
      printf("\n Envoye un OK au serveur ... ");
      strcpy(buf,"OK");
      long_buf = strlen(buf) +1;
      envoye = 
	       sendto(client, buf, long_buf,0,
                      (struct sockaddr *)&serveur, long_serveur);
       if(envoye < 0) 
         { 
         printf(" [FAILED]");
         perror("Cause");
         }
       printf(" [OK]");
       printf(" \n Le transfert est termine avec succe.");
       printf(" \n Ouvrir le fichier %s pour voir le resultat de la recpetion.",
		       nom_fich_recu);
     }


fclose(fd);
close(client);
printf("\n");
return 0;
}

//////////////////////////////////////////////////////////////////
//Procedure aui permet la creation d'une socket                //
//Elle attend le numero de port                               //
//et elle nou renvoi un descripteur                          //
//////////////////////////////////////////////////////////////

int cree_socket(int port)
{

  struct sockaddr_in serveur_addr;
  int serveur;
  
  // Creation du socket
  serveur = socket(AF_INET, SOCK_DGRAM, 0);
  if(serveur < 0)
    {
      perror(" [FAILED] \n");
      return(-1);
    }
  printf(" [OK]\n"); 
  // La famille a laquelle appartient le socket
  serveur_addr.sin_family = AF_INET;
  
  // Adresse specifique qui permet de dir au systeme
  // que je suis en ecoute sur tout les adresse IP entrantes
  serveur_addr.sin_addr.s_addr = htons(INADDR_ANY);
  
  // Le port utilise par le socket
  serveur_addr.sin_port = htons(port);

  // Attachement du socket au systeme
   printf("\n Attachement de la socket cree avec le systeme ... ");
  if(bind(serveur, (struct sockaddr *) &serveur_addr, sizeof(serveur_addr)) < 0)
    {
      printf(" [FAILED]\n");
      perror("Cause");
      return(-1);
    }
  printf(" [OK]"); 
  return serveur;
}

 Conclusion

Compilation du serveur: cc fudps.c -o serveur -lpthread
Execution du serveur:   ./serveur 1200


Compilation du client: cc fudpc.c -o client
Execution du client: ./client adresse_serveur num_port (pour une simulation sur une meme machine io faut utilise un numero de port different de 1200, et pour chaque client il faut utilise un nouveau numero de port)

Remarque importante:
--------------------

    Pour un bon fonctionnement il faut avoir un compte administrateur.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip TRANSFERT DE FICHIER VIA LE PROTOCOL TCP/IP
Source avec Zip CHEMIN CRITIQUE PAR LA METHODE PERT
SIMPLEX PRIMAL
Source avec Zip PROBLÈME DES 8 REINES GÉNÉRALISÉ
RECHERCHE DE MOTIF DANS UN TEXTE

 Sources de la même categorie

Source avec Zip SERVEUR MULTITHREAD [LINUX/WIN] par nipepsinicolas
Source avec Zip Source avec une capture SECURE REMOTE SHELL [WIN32] par ganjarasta
Source avec Zip Source avec une capture SUIVI DE PRODUCTION ONDULEUR PHOTOVOLTAÏQUE SOLARMAX par brunovan
Source avec Zip MINICHAT MULTI-CLIENT par wisar
SOCKET CPP par baptchr55

 Sources en rapport avec celle ci

Source avec Zip TRANSFERT DE FICHIER VIA LE PROTOCOL TCP/IP par Abdellah81

Commentaires et avis

Commentaire de max12 le 24/05/2006 00:27:21 administrateur CS

Sa doit être super interessant en multicasting, tu transfère des fichiers à plusieurs personnes super-plus-rapidement qu'avec TCP :D

Commentaire de Abdellah81 le 26/05/2006 21:11:04

Ce que vous disiez est vrai, mais avec TCP c'est plus sur. Mais meme malgré ca il y a peut de chance que des erreurs de transfert se produisent dans un reseau local.

Commentaire de sophia_amoureuse le 26/05/2006 21:42:27

Bravo Abdellah vous avez vraiment realise un tres bon travail.
Je l'avais essayer sous linux Suse9 il a bien marche, sauf que la recherche des fichier est tres lourde car mon disque est volumineu.
Est ce qu'il n'y a pas un moyen d'accéléré la recherche?
Thank you.

Commentaire de Abdellah81 le 30/05/2006 14:21:49

Dsl mais il n'y a aucun moyen d'accelere la recherche, sauf en evitant les repertoires systemes et  ceux des fichier special like etc, dev, proc ...
Il y a des moyens un peut saufestique pour l'accélérationde la recherche comme par exemple l'indexage des fichiers. cela permet d'effectuer une recherche plus rapide en cherchant les noms des fichiers dans les fichiers index qui contient une table d'association nom de fichier == chemin.

Commentaire de kspham le 03/06/2006 06:56:35

Avez-vous la version WINDOWS ?

Commentaire de sophia_amoureuse le 05/06/2006 15:19:37

DSL, j'ai pas la version windows; mais sa ce peut etre executer sous windows, en utilisant gcc ou dev-cpp. ou en utilisant le simulateur cygwin.

Commentaire de brad1024 le 18/08/2006 16:22:37

dzl, mais je n'arrive pa a compiler le serveur avec ce que tu as donné.
ca me donne :

fudps.c: Dans la fonction «main» :
fudps.c:105: attention : incompatible implicit declaration of built-in function «exit»
fudps.c:116: attention : incompatible implicit declaration of built-in function «exit»
fudps.c:132: attention : incompatible implicit declaration of built-in function «malloc»
fudps.c:137: attention : incompatible implicit declaration of built-in function «exit»
fudps.c:162: attention : incompatible implicit declaration of built-in function «exit»
fudps.c:185: attention : pointer targets in passing argument 6 of «recvfrom» differ in signedness
fudps.c:192: attention : incompatible implicit declaration of built-in function «exit»
fudps.c:284: attention : incompatible implicit declaration of built-in function «exit»
fudps.c: Dans la fonction «th_trait» :
fudps.c:382: attention : incompatible implicit declaration of built-in function «malloc»
fudps.c:423: attention : pointer targets in passing argument 6 of «recvfrom» differ in signedness
fudps.c:446: attention : pointer targets in passing argument 6 of «recvfrom» differ in signedness
fudps.c:567: attention : pointer targets in passing argument 6 of «recvfrom» differ in signedness
fudps.c:657: attention : pointer targets in passing argument 6 of «recvfrom» differ in signedness
/usr/bin/ld: ne peut trouver -lpthreqd
collect2: ld a retourné 1 code d'état d'exécution

je travaille sous ubuntu

Commentaire de brad1024 le 18/08/2006 16:58:29

dzl de vous deranger, je suis arrivé a compiler le serveur
ma question est qu'est ce que "motif" veux dire??

Commentaire de Abdellah81 le 20/08/2006 20:05:53

Salut BRAD1024
Motif est la chaine qu'on veut chercher dans le fichier distant.
                                                        Bonne chance

Commentaire de brad1024 le 20/08/2006 20:25:40

merci pour la précision.
tu as mis dans le code :
// on evite les repertoires systemes
// si vous voulez effectue une recherche dans ses repertoires
// il faut les supprimes, mais le temps de recherche augmentera
// considerablement

c'est ce que j'ai fait mais ca ne marche pas, apparemment c'est un problème de pile, j'ai essayé d'augmenter la taille de la pile mais le serveur se plante "erreur de segmentation"

Commentaire de badr07 le 23/08/2006 22:03:10

Bienjouer Abdelah!!!
Super ton propogramme!!!!!
10/10 !!!!!!!!!!
Ca va m'aider pour mon Finir chevale de troie...
Quand j'l'aurias Finish j'te passerai le lien de telechargement
@+
bslama les gas...!

Commentaire de Abdellah81 le 12/09/2006 16:23:57

Bslama badr et bonne chance dans ton projet.
a+

Commentaire de bariland le 12/03/2009 17:51:36

bravo abdallah .je cherchait un code comme celui la
ca fait plaisir
moi ausi j'ai un projet fin  d'etude en languge c
le transfert de fichier de tous type et un chat complet
ca va m'aider

Commentaire de gogoben le 27/04/2010 11:28:19

salut abdallah, ton code est super, mais je reçois ceci en l'exécutant :

Cause: Address family not supported by protocol
4.67.232.0:1032 demande la connexion au serveur ...

Je ne comprends pas d'où cette erreur vient, une solution ?

Merci.

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,092 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales