Académique Documents
Professionnel Documents
Culture Documents
1 - Introduction : 2 - Les sockets sous Linux : 3 - Un client/serveur : 3-1 Version TCP : 3-1-a- Domaine INTERNET : i. Code serveur : ii. Code client : 3-1-b- Domaine UNIX : i. Code serveur : ii. Code client : 3-2 Version UDP : 3-2-a- Domaine INTERNET : i. Code serveur : ii. Code client : 3-2-b- Domaine UNIX : i. Code serveur : ii. Code client : 4 - Un serveur multiclients (Avec FORK()) : 4-1-Introduction : Raliser par : TAHIR ZAKARIAE 4-2- Version TCP : 4-2-a- Domaine INTERNET : i. Code serveur : 5- Un Serveur pour le transfert de fichiers : 5-1- Version TCP : 5-1-a- Domaine INTERNET : i. Code serveur : 6- Un Serveur pour le transfert de fichiers multiclients (Avec FORK()) : 6-1- Version TCP : 6-1-a- Domaine INTERNET : i. Code serveur : 7- Un client et un Serveur pour le chat et le transfert de fichiers multiclients amlior :
Les sockets en C
FELOUACH KHALID
exemple, la constante est AF_UNIX AF_INET pour le domaine internet et AF_NS pour le domaine NS. Les types de sockets sont les suivants: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_NS. Par exemple pour crer une socket utilisant le protocole TCP, l'appel systme suivant peut tre effectu :
1 Introduction :
Code C : Les sockets sont des flux de donnes, permettant des machines locales ou distantes de int s; communiquer entre elles via des protocoles. s = socket (AF_INET, SOCK_STREAM, 0); Les diffrents protocoles sont TCP qui est un protocole dit "connect", et UDP qui est un protocole dit "non connect". La plupart du temps, la valeur par dfaut du Position des sockets dans le modle OSI : Les sockets champ protocol est suffisante mme si on peut lui se situent juste au-dessus de la couche transport du attribuer une valeur particulire. modle OSI (protocoles UDP ou TCP), elle-mme utilisant les services de la couche rseau (protocole IP / ARP). Attribution d'une adresse : 2 - Les sockets sous Linux : Cration d'une socket : La cration d'une socket se fait partir de l'appel systme suivant: Code C :
#include <sys/types.h> #include <sys/socket.h> int s, domain, type, protocol; s = socket (domain, type, protocol);
Une socket est cre sans adresse et ne permet pas tout de suite d'changer des donnes. Pour pouvoir y remdier, il faut lui associer une adresse. Pour les domaines Internet et NS, cette association est compose d'une adresse IP locale et d'un port local tandis que pour le domaine UNIX, il s'agit d'un nom de fichier. Dans le domaine Internet, l'attribution d'une adresse une socket peut tre faite automatiquement par le systme, et c'est gnralement le cas pour un processus client, mais il est souvent ncessaire de l'expliciter dans le cas d'un processus serveur qui doit contrler le port sur lequel il va couter.
L'adresse gnrique d'une socket est dfinie Cet appel systme permet de crer une socket par la structure suivante: appartenant domain et possdant la proprit type. Il renvoie un nombre entier -1 en cas d'chec qui Code C : peut tre assimil un descripteur de fichier. Le #define SOCK_MAXADDRLEN 255 /* adresse la champ protocol peut ne pas tre spcifi valeur plus longue possible */ gale zro. Dans ce cas, le systme choisit un protocole appropri parmi les diffrents protocoles struct sockaddr { utiliss dans le domaine de communication considr unsigned char sa_len; /* longueur et supportant le type de socket requis. totale */ Les champs domain et type sont choisis parmi les constantes dfinies dans le fichier <sys/socket.h>. Pour le domaine UNIX par
sa_family_t sa_family; /* famille d'adresse */ char sa_data[14]; /* valeur de l'adresse */
};
addrlen. La fonction renvoie -1 en cas d'chec. Aprs avoir effectu cette operation, la socket est desormais reference et peut donc recevoir et envoyer des donnes.
Exemple :
Cette adresse n'est gnralement pas directement utilise en tant que telle servant uniquement de rfrence gnrique pour les appels systmes. la place, une adresse plus spcifique est utilise pour chaque domaine de communication. Pour le domaine internet par exemple, la structure suivante dfinie dans le fichier netinet/in.h remplace la version prcdente: Code C :
struct sockaddr_in { /* longueur totale */ uint8_t sin_len; /* famille d'adresse */ sa_family sin_family; /* numero de port */ in_port_t sin_port; /* valeur sur 32 bits de l'adresse*/ struct in_addr sin_addr; /* champ rempli de zeros */ char sin_zero[8]; };
Code C :
struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(1100); addr.sin_addr.s_addr = INADDR_ANY; if(-1 == bind(s,(const void *)&addr, sizeof(addr))) { perror("error bind failed"); close(s); exit(EXIT_FAILURE); }
tablissement d'une connexion : Pour des sockets de type SOCK_STREAM, l'tablissement de la connexion ncessite un mcanisme diffrent pour le client et pour le serveur. Ct serveur, la socket coute sur une adresse donne (spcifie par bind) par un appel listen puis accepte chaque connexion entrante par un appel accept: Code C :
int listen(int s, unsigned int maxconn);
De la mme maniere, il existe galement une adresse sockaddr_un et sockaddr_ns pour les domaines unix et NS. L'association d'une socket avec une adresse se fait par l'intermediaire de l'appel systme bind: Code C :
#include <sys/types.h> #include <sys/socket.h> int bind (int s, const struct sockaddr *addr, socklen_t addrlen);
ou s est la socket associe avec l'adresse pointe par addr dont la longueur totale est
s dsigne la socket serveur. maxconn spcifie le nombre maximum de connexions simultanes que pourra accepter la socket. Une valeur typique est 50. addr et addrlen reoivent au retour de la fonction l'adresse de l'autre ct de la connexion. accept retourne une nouvelle socket qui sera utilise pour la connexion -1 en cas d'erreur. Ainsi, 3
une mme socket serveur peut avoir plusieurs connexions actives simultanment. Exemple: Code C :
if(-1 == listen(s, 50)) { perror("error listen failed"); close(s); exit(EXIT_FAILURE); } for(;;) { int conn = accept(s, NULL, NULL); if(0 > conn ) { perror("error accept failed"); close(s); exit(EXIT_FAILURE); } Effectuer les oprations dsires sur la nouvelle socket conn... */ } /*
Code C :
struct sockaddr_in addr; addr.sin_family = PF_INET; addr.sin_port = htons(1100); inet_pton(PF_INET, "192.168.1.3", &addr.sin_addr); if(-1 == connect(s, (const void *)&addr, sizeof(addr))) { perror("connect failed"); close(s); exit(EXIT_FAILURE); }
Pour une socket de type SOCK_DGRAM (UDP), Il n'y a pas de connexion proprement parler. L'appel connect est nanmoins possible et spcifie l'adresse de destination par dfaut de la socket. Transfert de donnes : L'envoi de donnes est effectu par l'appel send et la reception par l'appel recv: Code C :
#include <sys/socket.h> int send (int s, void *buffer, size_t size, int flags); int recv (int s, void *buffer, size_t size, int flags);
o s est la socket connecter, et addr l'adresse de destination laquelle se connecter. Si aucun appel bind n'a t effectu prcdemment sur la socket, l'adresse locale (et en particulier le numro de port) est choisie par le systme. Exemple:
Pour des sockets de type SOCK_DGRAM, non connectes, il peut tre ncessaire de prciser l'adresse de destination lors de l'envoi et de rcuprer l'adresse source lors de la rception. Pour cela, on utilise les fonctions sendto et recvfrom:
Code C : 4
lu; #include <sys/socket.h> int sendto (int s, void *buffer, size_t size, int flags, struct sockaddr *addr, socklen_t length); static struct sockaddr_in serv_addr, cli_addr;//adresse locale et du client char recvline[256]; //taille du buffer de lecture et criture char sendline[256]; int recvfrom (int s, void *buffer, size_t size, int flags, struct sockaddr *addr, socklen_t *length); //Creation de la socket , en verifiant que si la socket a t bien cre if((sockfd=socket(AF_INET,SOCK_STREAM,0))< 0) printf("error socket\n"); //Attribution d'adresse
Fermeture d'une socket : Cette fonction ferme le descripteur s, dans notre cas, elle fermera simplement notre socket. Code C :
int close(int s);
serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=htonl(INADDR_ANY ); serv_addr.sin_port=htons(atoi(argv[1]));// ou htons(NUMPORT) printf("le numro de port est %s\n",argv[1]); //liaison de la socket avec la structure serv_addr,en verifiant que si la socket a t bien associe a cette structure if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) perror("bind"); //on met le serveur a l'ecoute,avec 5 represente le nombre de clients max qu'ils peuvent connecter avec notre serveur listen(sockfd,5); clilen=sizeof(cli_addr); printf("Patientez pendant que le client se connecte sur le port %s...\n",argv[1]); //Cette fonction accepte la connexion d'un socket sur le socket
3 - Un client/serveur :
3-1 Version TCP : 3-1-a- Domaine INTERNET : i. Code serveur : Code Serveur.c :
#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> main(int argc, char * argv[]) { int sockfd; //descripteur de socket de service int newsockfd; //descripteur de socket de client int clilen; //taille de ladresse du client int max=256; // le nombre doctets
sockfd. newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); if (newsockfd<0){ printf("accept error\n"); exit(0); } printf("un client est connect:\n"); //tant que le serveur ne ferme pas la connexion on continue. while(strcmp(send,"exit")!=0){ //recevoire l'info read(newsockfd,recvline,256); printf("\n\tClient : %s",recvline); ////si le client ferme la connexion on sort. if(strcmp(recvline,"exit")==0) break; printf("\n\tServeur : "); gets(send); //envoyer l'info write(newsockfd,send,sizeof(send)); } //fermeture de la socket. close(newsockfd); }
{ int sockfd,servlen,max=50,n; struct sockaddr_in serv_addr; char sendline[256]; char recvline[256]; //Attribution d'adresse serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr(argv[2 ]); serv_addr.sin_port=htons(atoi(argv[1])); /* Creation de la socket , en verifiant que si la socket a t bien cre */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))< 0) { printf("erreur creation de socket\n"); exit(0); } /* Si la connection avec le seveur a t mal passe alors on sort en affichant le message "error connexion" */ if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) { printf("error connexion\n"); exit(0); }
while(strcmp(recv,"exit")!=0)
int servlen; char recvline[256]; char c; char send[256]; //Creation de la socket if((sockfd=socket(AF_UNIX,SOCK_STREAM,0))< 0) printf("error socket\n"); //Attribution d'adresse serv_addr.sun_family=AF_UNIX; bcopy(argv[1],serv_addr.sun_path,strlen(ar gv[1])); printf("le chemin est %s\n",argv[1]); servlen=strlen(serv_addr.sun_path) +sizeof(serv_addr.sun_family); //liaison de la socket avec la structure if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) perror("bind");
//reception du message read(sockfd,recv,256); printf("\n\t Serveur : %s",recv); } //fermeture de la socket. close(sockfd); exit(0); }
//on met le serveur a l'ecoute listen(sockfd,1); clilen=sizeof(cli_addr); newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); if(newsockfd<0) { printf("accept error\n"); exit(0); } printf("connexion accepte\n"); while(strcmp(send,"exit")!=0) {
//reception du message read(newsockfd,recvline,256); printf("\n\tClient : %s",recvline); if(strcmp(recvline,"exit")==0) break; //envoie du message printf("\n\tServeur : "); gets(send); write(newsockfd,send,sizeof(send)); } //fermer la connexion close(newsockfd); }
int clilen;
serv_addr.sun_family=AF_UNIX; bcopy(argv[1],serv_addr.sun_path,strlen(ar gv[1])); servlen=strlen(serv_addr.sun_path) +sizeof(serv_addr.sun_family); if(connect(sockfd,(struct sockaddr *)&serv_addr,servlen)<0) \n"); printf("error de connexion
main(int argc,char *argv[]) { static struct sockaddr_un cli_addr,serv_addr; int i; int sockfd; int servlen; char sendline[256]; char recv[256]; int newsockfd;
} close(sockfd); exit(0); }
Code Serveur.c :
#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include<strings.h> main(int argc, char * argv[]) { int sockfd; //descripteur de socket de service int newsockfd; //descripteur de socket de client int clilen; //taille de ladresse du client int max=256; // le nombre doctets lu static struct sockaddr_in serv_addr, cli_addr;//adresse locale char recvline[256]; //taille du buffer de lecture et criture char send[256]; if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0 ) printf("error socket\n"); //Attribution d'adresse serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=htonl(INADDR_ANY ); serv_addr.sin_port=htons(atoi(argv[1])); printf("le numro de port est : %s\n",argv[1]); if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) perror("bind"); clilen=sizeof(cli_addr); do{ //reception du message }
}while(strcmp(recvline,"exit")!=0); close(sockfd);
10
sendto(sockfd,sendline,sizeof(sendline) ,0,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); if(strcmp(recvline,"exit")==0) break; //reception du message recvfrom(sockfd,recv,256,0,(struct sockaddr *)&serv_addr,&serlen); printf("\n\tServeur : %s",recvline); } //fermer la connexion close(sockfd); }
pid_t ppid = getppid(); //Obtenir le processus parent pidf = fork(); //Cration du processus enfant if (pidf == 0) { //On est dans le processus enfant printf("Fils - Mon PID est %d\n", pid); printf("Fils - mon PID parent est %d.\n", ppid); } else { //On est dans le processus parent printf("Parent - Mon pid est %d\n", pid); printf("Parent - pidf est %d.\n", pidfils); } return 0 ; }
4-2- Version TCP : 4-2-a- Domaine INTERNET : i. Code serveur : Code Serveur.c :
#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include <string.h> #include <signal.h> /*Pour gestion des signaux*/ #include <wait.h> /*Pour gestion des signaux*/ main(int argc, char * argv[]) { int sockfd; //descripteur de socket de service int newsockfd; //descripteur de socket de client int clilen; //taille de l'adresse du client
11
int i=0;//Compteur pour faire la diffrence entre les clients en leur donnant des numero int max=250; // le nombre d'octets lu; struct sockaddr_in loc_addr, cli_addr;//adresse locale et du client char recvline[256],sendline[256]; //taille du buffer de lecture et criture if((sockfd=socket(AF_INET,SOCK_STREAM,0) )<0) printf("error socket\n"); loc_addr.sin_family=AF_INET; loc_addr.sin_addr.s_addr=htonl(INADDR_AN Y); loc_addr.sin_port=htons(atoi(argv[1]));/ /ou htons(NUMPORT) printf("le numero de port est %s\n",argv[1]);
PERE/FILS"); } //PROCESSUS FILS if(pid==0){ do{ read(newsockfd,recvline,256); printf("\n\tClient %d: %s",i,recvline); break; if(strcmp(recvline,"end")==0) printf("\n\tServer : "); gets(sendline);
if(bind(sockfd,(struct sockaddr *)&loc_addr,sizeof(loc_addr))<0) perror("bind"); listen(sockfd,5); clilen=sizeof(cli_addr); pid_t pid; while(1){ newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); i++; //on va crer un processus. pid=fork(); //fork a chou, on n'a pas pu crer de processus fils. if(pid==-1){ printf("Erreur dans la disjonction }
12
envoie une chaine prcise ceci main(int argc, char * argv[]) { FILE *f; int sockfd; //descripteur de socket de service int newsockfd; //descripteur de socket de client int clilen; //taille de l'adresse du client int max=250; // le nombre d'octets lu; struct sockaddr_in loc_addr, cli_addr;//adresse locale et du client char recvline[256],sendline[256]; //taille du buffer de lecture et criture if((sockfd=socket(AF_INET,SOCK_STREAM,0) )<0) printf("error socket\n"); loc_addr.sin_family=AF_INET; loc_addr.sin_addr.s_addr=htonl(INADDR_AN Y); loc_addr.sin_port=htons(atoi(argv[1]));/ /ou htons(NUMPORT) printf("le numero de port est %s\n",argv[1]); if(bind(sockfd,(struct sockaddr *)&loc_addr,sizeof(loc_addr))<0) perror("bind"); listen(sockfd,5); clilen=sizeof(cli_addr); newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); //on lit le nom de fichier demmander par le client read(newsockfd,recvline,256); printf("\t\t\n\nClient demande le fichier : %s\n", recvline); //si le fichier n'existe pas alors on if(!fopen(recvline,"rb")){ strcpy(sendline,"Le fichier n'existe pas !"); write(newsockfd,sendline,sizeof(sendline)) ; printf("\t\nLe fichier : %s n'existe pas !\n", recvline); } //sinon else { printf("\t\nLe fichier : %s existe ,programme client entrain de lire !\n", recvline); //on ouvre le fichier en lecture binaire f=fopen(recvline,"rb"); //tant que on n'est pas arriv a la fin du fichier on envoie. while(! feof(f)) { //lecture du fichier source fread(sendline, 1, sizeof(sendline) , f); //envoie du chaine lise apartir du fichier source write(newsockfd,sendline,sizeof(sendline)) ; //vidage du buffer bzero(sendline,sizeof(sendline)) ; } /* a la fin de lenvoie du fichier , on envoie la chaine "Fin" pour que le client arrete la lecture */ strcpy(sendline,"Fin"); write(newsockfd,sendline,sizeof(sendline)) ; //fermeture du fichier fclose(f);
13
close(newsockfd); } close(sockfd); }
//on demande au client de donner le nom de fichier voulu printf("\t\nDonner le nom de fichier : "); gets(sendline); write(sockfd,sendline,sizeof(sendline)); read(sockfd,recvline,256); /* si la reponse du serveur egale a la chaine "Le fichier n'existe pas !" alors le fichier inexistant */ if(strcmp(recvline,"Le fichier n'existe pas !")==0) printf("\t\nFichier demander n'existe pas !");
else{ //on demande le nom d'enregistrement du fichier printf("\t\nDonner le nom dont cous voullez enregister le fichier : "); gets(recu); printf("\t\nProgramme client entrain de lire et ecrire depuis le fichier source ...\n"); //on cree le fichier f=fopen(recu,"w+b"); , f); fwrite(recvline, 1, sizeof(recvline)
//tant que la chaine "Fin" n'est encore receptionne //on lit apartir du fichier source while(strcmp(recvline,"Fin")!=0){ read(sockfd,recvline,256); break; if(strcmp(recvline,"Fin")==0)
14
5-2- Version UDP : 5-2-a- Domaine INTERNET : i. Code serveur : Code Serveur.c :
#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include <string.h> #include<stdlib.h> main(int argc, char * argv[]) { FILE *f; int sockfd; //descripteur de socket de service int newsockfd; //descripteur de socket de client int clilen; //taille de l'adresse du client int max=250; // le nombre d'octets lu; struct sockaddr_in loc_addr, cli_addr;//adresse locale et du client char recvline[256],sendline[256]; //taille du buffer de lecture et criture if((sockfd=socket(AF_INET,SOCK_DGRAM,0)) <0) printf("error socket\n"); loc_addr.sin_family=AF_INET; loc_addr.sin_addr.s_addr=htonl(INADDR_AN if(bind(sockfd,(struct sockaddr *)&loc_addr,sizeof(loc_addr))<0) perror("bind"); listen(sockfd,5); clilen=sizeof(cli_addr); //on lit le nom du fichier demand par le client recvfrom(sockfd,recvline,max,0,(struct sockaddr *)&cli_addr,&clilen); printf("\t\t\n\nClient demande le fichier : %s\n", recvline); //si le fichier n'existe pas if(!fopen(recvline,"rb")){ strcpy(sendline,"Le fichier n'existe pas"); sendto(sockfd,sendline,sizeof(sendline),0, (struct sockaddr*)&cli_addr,clilen); printf("\t\nLe fichier : %s n'existe pas !\n", recvline); } //sinon else { strcpy(sendline,"Le fichier existe"); sendto(sockfd,sendline,sizeof(sendline),0, (struct sockaddr*)&cli_addr,clilen); printf("\t\nLe fichier : %s existe\n", recvline); f=fopen(recvline,"rb"); while(! feof(f)) { fread(sendline,1,
15
sizeof(sendline), f); sendto(sockfd,sendline,sizeof(sendline),0, (struct sockaddr*)&cli_addr,clilen); } strcpy(sendline,"Fin"); sendto(sockfd,sendline,sizeof(sendline),0, (struct sockaddr*)&cli_addr,clilen); fclose(f);
<0) printf("erreur creation de socket\n"); servlen=sizeof(serv_addr); if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) printf("error connexion\n"); //on lit le nom du fichier demand par le client
} close(sockfd); }
printf("\t\nDonner le nom de fichier : "); gets(sendline); sendto(sockfd,sendline,sizeof(sendline), 0,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); recvfrom(sockfd,recvline,max,0,(struct sockaddr *)&serv_addr,&servlen); //si le fichier n'existe pas if(strcmp(recvline,"Le fichier n'existe pas")==0) printf("\t\nFichier demande n'existe pas !\n"); //sinon else{ printf("\t\nDonner le nom dont cous voullez enregister le fichier : "); gets(recu); printf("\t\nProgramme client entrain de lire et ecrire depuis le fichier source ...\n"); f=fopen(recu,"wb+"); while(strcmp(recvline,"Fin")!=0){ recvfrom(sockfd,recvline,256,0, (struct sockaddr *)&serv_addr,&servlen); break; if(strcmp(recvline,"Fin")==0)
16
} close(sockfd); }
if(bind(sockfd,(struct sockaddr *)&loc_addr,sizeof(loc_addr))<0) perror("bind"); listen(sockfd,5); clilen=sizeof(cli_addr); pid_t pid; while(1){ newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); //on va crer un processus. pid=fork(); //si fork a chou, on n'a pas pu crer de processus fils. if(pid==-1) printf("Erreur dans la disjonction PERE/FILS"); //PROCESSUS FILS if(pid==0){ read(newsockfd,recvline,256); printf("\t\t\n\n un client demande le fichier : %s\n", recvline); if(!fopen(recvline,"rb")){ strcpy(sendline,"Le fichier n'existe pas !\n"); write(newsockfd,sendline,sizeof(sendline)) ; printf("\t\nLe fichier : %s n'existe pas !\n", recvline); } else{ f=fopen(recvline,"rb"); while(! feof(f)){ fread(sendline,1, sizeof(sendline), f); write(newsockfd,sendline,sizeof(sendline)) ; } strcpy(sendline,"Fin"); write(newsockfd,sendline,sizeof(sendline)) ; fclose(f); } close(newsockfd); } } close(sockfd); }
17
7- Un client et un Serveur pour le chat et le transfert de fichiers multiclients amlior : 7-1- code serveur :
int ajouter(per *t,int *n,per p) { FILE *f; if(recherchlogin(t,*n,p.login)==-1) { strcpy(t[(*n)].login,p.login); strcpy(t[(*n)].passe,p.passe); (*n)++; f=fopen("f.bin","ab"); fwrite(&p,1, sizeof(per), f); fclose(f); return 1; return 0;
Code Serveur.c :
#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include <string.h> #include<stdlib.h> #include <string.h> /*Pour memset() !*/ #include <signal.h> /*Pour gestion des signaux*/ #include <wait.h> /*Pour gestion des signaux*/ /*Petite fonction qui traite les signaux de fins des processus fils...*/ typedef struct s { char login[20]; char passe[20]; }per; void remplir(per *t,int *n){ FILE *f; f=fopen("f.bin","rb+"); fseek(f, 0, SEEK_SET); (*n)=0; while(! feof(f)) { fread(&t[(*n)],1, sizeof(per), f); (*n)++; } (*n)--; fclose(f);
} else
void chat(int newsockfd,char * login) { char recvline[256]; char sendline[256]; while(strcmp(sendline,"bye")!=0) { read(newsockfd,recvline,256); printf("\n\t\t%s : %s",login,recvline); if(strcmp(recvline,"bye")==0) break; printf("\n\t\tServeur : "); gets(sendline); write(newsockfd,sendline,sizeof(sendline)) ; } } int envoifich(int newsockfd,char *fich) { FILE *fic; char buffer[256]; fic=fopen(fich,"rb"); if(fic==NULL){ printf("impossible d'ouvrir le fichier \n"); write(newsockfd,"0",sizeof("0")); return 0; } else{ write(newsockfd,"1",sizeof("1")); while(!feof(fic)){
int recherchlogin(per *t,int n,char *ch) { int i=0; while((i<n)&&(strcmp(t[i].login,ch)! =0)) i++; if(i==n) return -1; else return i;
18
fread(buffer,1,256,fic);
write(newsockfd,buffer,sizeof(buffer)); } strcpy(buffer,"FIN"); write(newsockfd,buffer,sizeof(buffer)); fclose(fic); return 1; } } main(int argc, char * argv[]) { per p,t[7]; pid_t pid; int i=0,j=0,n=0; int sockfd; int newsockfd; int clilen; struct sockaddr_in loc_addr, cli_addr; char recvline[256],sendline[256]; int choix,choix_2; int r; if((sockfd=socket(AF_INET,SOCK_STREAM,0))< 0) printf("error socket\n"); loc_addr.sin_family=AF_INET; loc_addr.sin_addr.s_addr=htonl(INADDR_ANY) ; loc_addr.sin_port=htons(atoi(argv[1])); printf("le numero de port est %s\n",argv[1]); if(bind(sockfd,(struct sockaddr *)&loc_addr,sizeof(loc_addr))<0) perror("bind"); remplir(t,&n); listen(sockfd,5); clilen=sizeof(cli_addr); while(1){ newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); if (newsockfd<0){ printf("accept error\n"); exit(0);
} j++; //ouverture d'un "canal" client avec recup de ses infos. pid=fork(); //disjoinction Pre-Fils if(pid==-1){ //ERREUR DE DISJONCTION printf("Erreur dans la disjonction PERE/FILS"); } if(pid==0){ //PROCESSUS FILS /*Instructions Fils */ read(newsockfd,recvline,256); choix=atoi(recvline); switch(choix){ case 1:{ printf("Le client a choisi de se connecter \n "); recv(newsockfd, &p, sizeof(p), 0); printf("Le client a choisi de se connecter \n ");
i=recherchlogin(t,n,p.login); if(i==-1){ strcpy(sendline,"errcomp"); write(newsockfd,sendline,sizeof(sendline)) ; //printf("ce compte n'existe pas\n"); } else{ if(strcmp(t[i].passe,p.passe)!=0){ strcpy(sendline,"errpass"); write(newsockfd,sendline,sizeof(sendline)) ; //printf("mo t de passe erronne\n"); } else{ strcpy(sendline,"connexion"); write(newsockfd,sendline,sizeof(sendline)) ; printf("\n le client %s est connecte avec le numero
19
printf("Login : if(ajouter(t,&n,p)==0) printf("Ajout du compte client a echouer \n "); else { printf("Le compte client a ete bien ajouter \n "); goto CHAT; } break; } default: close(newsockfd); break; } } } } close(sockfd);
case 1:{
printf(" CHAT\n"); chat(newsockfd,p.login); CHAT; goto break; } case 2:{ printf(" TRANSFERT\n"); read(newsockfd,recvline,256); r=envoifich(newsockfd,recvline); if(r==0) printf("\n\t\t le fichier n'existe pas !"); else printf("\n\t\t le fichier existe le client entrain de telecharger !"); goto CHAT; break; } default:{ printf(" \n"); } } } } break; } case 2:{ printf("Le client a choisi de crer un compte \n "); recv(newsockfd, &p, sizeof(p), 0); printf("Login : %s\n",p.login); break;
Code Client.c :
#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<arpa/inet.h> #include <string.h> #include<stdlib.h> typedef struct s { char login[20]; char passe[20]; }per; int menu_1(){ int choix; char ch[2]; printf("\n\t\t printf("\n\t\t printf("\n\t\t printf("\n\t\t
::::: MENU ::::: "); 1-SE CONNECTE "); 2-CREE UN COMPTE "); 3-QUITER- ");
20
} int menu_2(){ int choix; char ch[2]; printf("\n\t\t printf("\n\t\t printf("\n\t\t printf("\n\t\t
} main(int argc,char** argv) { per p; char nom_fic[26]; int sockfd,servlen,max=50,n; struct sockaddr_in serv_addr; char sendline[256]; char recvline[256]; char recu[260]; int i; int choix,choix_2; FILE *f; serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr("127.0 .0.1"); serv_addr.sin_port=htons(atoi(argv[1])); printf("\n"); if((sockfd=socket(AF_INET,SOCK_STREAM,0))< 0) printf("erreur creation de socket\n"); if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) printf("error connexion\n");
::::: MENU ::::: "); 1-CHAT "); 2-TRANSFERT "); 3-QUITER- ");
printf("\n\n\t\t Votre choix : "); scanf("%d",&choix); gets(ch); system("clear"); return choix; } void chat(int sockfd) { char sendline[256]; char recvline[256]; while(strcmp(recvline,"bye")!=0) { printf("\n\t\tClient : "); gets(sendline); write(sockfd,sendline,sizeof(sendline)); if(strcmp(sendline,"bye")==0) break; read(sockfd,recvline,256); printf("\n\t\tServeur : %s",recvline); } } int recoifichier(int sockfd,char *fich) { FILE *fic; char recv[256]; int res=-1; fic=fopen(fich,"wb"); do { read(sockfd,recv,sizeof(recv)); if(strcmp(recv,"FIN")==0){ res=0; break; } fwrite(recv, 1, sizeof(recv) , bzero(recv,sizeof(recv)); }while(1); fclose(fic); return res;
SE CONNECTE \n");
write(sockfd,"1",sizeof("1")); printf("\t\nLogin : "); gets(p.login); printf("\t\nPasse : "); gets(p.passe); send(sockfd, &p, sizeof(p), 0);
fic);
21
fichier : "); read(sockfd,recvline,256); if(strcmp(recvline,"errcomp")==0) printf("Ce compte n'existe pas\n"); else { if(strcmp(recvline,"errpass")==0) printf("Mot de passe incorrect\n"); else { gets(recu); i=recoifichier(sockfd,recu); if(i==0) printf("\n\t\t le fichier a ete bien recu !"); else printf("\n\t\t le fichier n'a pas ete recu !"); } else printf(" le fichier n existe pas\n"); goto CHAT; break; } case 3 :{ case 1 :{ printf("\n\t\t 1-CHAT "); write(sockfd,"1",sizeof("1")); chat(sockfd); goto CHAT; break; } case 2 :{ printf("\n\t\t 2-TRANSFERT "); write(sockfd,"2",sizeof("2")); printf("\n\t\t Donner le nom du fichier que vous voullez recu : "); gets(sendline); write(sockfd,sendline,sizeof(sendline)); read(sockfd,recvline,256); if(strcmp(recvline,"1")==0) { printf("\n\t\t Donner le nom d'enregistrement du printf("\t\nPasse : "); gets(p.passe); send(sockfd, &p, sizeof(p), 0); goto CHAT; } break; } case 2 :{ printf("\n\t\t 2CREE UN COMPTE "); write(sockfd,"2",sizeof("2")); printf("\t\nLogin : "); gets(p.login); } } :{ printf("\n\t\t 3-QUITER- "); exit(0); break; } default
22
QUITER- \n");
write(sockfd,"2",sizeof("3")); exit(0); break; } default :{ printf("\n\t\t Votre choix est incorrecte ! \n"); break; } } } close(sockfd); }
23