Vous êtes sur la page 1sur 23

Sommaire :

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);

int accept(int s, 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 :

Ct client, la connexion est effectue par l'appel connect: Code C :


#include <sys/socket.h> int connect(ins s, struct sockaddr *addr, socklen_t addrlen);

#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); }

ii. Code client : Code Client.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)

while(strcmp(recv,"exit")!=0)

{ //envoie du message printf(" \n\t Client : "); gets(sendline);

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");

write(sockfd,sendline,sizeof(sendline)); //si le client ferme la connexion on sort. break; if(strcmp(sendline,"exit")==0)

//reception du message read(sockfd,recv,256); printf("\n\t Serveur : %s",recv); } //fermeture de la socket. close(sockfd); exit(0); }

3-1-b- Domaine UNIX : i. Code serveur : Code Serveur.c :


#include<stdio.h> #include<stdlib.h> #include<sys/socket.h> #include<sys/types.h> #include<sys/un.h> #include<string.h> main(int argc,char* argv[]) { static struct sockaddr_un cli_addr,serv_addr; int i; int sockfd; int newsockfd; int clilen;

//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;

if((sockfd=socket(AF_UNIX,SOCK_STREAM,0))< 0) socket\n"); printf("erreur creation de

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

ii. Code client : Code Client.c :


#include<stdio.h> #include<stdlib.h> #include<sys/un.h> #include<sys/socket.h> #include<sys/types.h> #include<string.h>

while(strcmp(recv,"exit")!=0) { printf(" \n\t Client : "); gets(sendline);

write(sockfd,sendline,sizeof(sendline)); break; if(strcmp(sendline,"exit")==0) //reception du message read(sockfd,recv,256); %s",recv); printf("\n\t Serveur :

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); }

3-2 Version UDP : 3-2-a- Domaine INTERNET : i. Code serveur :

printf("\n\tClient : %s",recvline); printf("\n\tServeur : "); gets(send); //envoie du message sendto(sockfd,send,sizeof(send),0,(struct sockaddr*)&cli_addr,clilen);

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);

ii. Code client : Code Client.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,servlen,max=256,n; struct sockaddr_in serv_addr,cli_addr; char sendline[256]; char recv[256]; int clilen; //Attribution d'adresse serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr("127.0 .1.1"); serv_addr.sin_port=htons(atoi(argv[1])); if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0 ) printf("erreur creation de socket\n"); clilen=sizeof(cli_addr); do{ //envoie du message printf("\n\tClient : "); gets(sendline);

recvfrom(sockfd,recvline,max,0,(struct sockaddr *)&cli_addr,&clilen);

sendto(sockfd,sendline,sizeof(sendline),0, (struct sockaddr *)&serv_addr,clilen); //reception du message recvfrom(sockfd,recv,max,0,

(struct sockaddr *)&cli_addr,&clilen); printf("\n\tServeur : %s",recv); }while(strcmp(sendline,"exit")!=0); close(sockfd); }

printf("\n\tServeur : "); gets(send); sendto(sockfd,send,sizeof(send),0, (struct sockaddr*)&cli_addr,clilen); } //fermer la connexion close(newsockfd); }

3-2-b- Domaine UNIX : i. Code serveur : Code Serveur.c :


#include<stdio.h> #include<stdlib.h> #include<sys/socket.h> #include<sys/types.h> #include<sys/un.h> #include<string.h> main(int argc,char* argv[]) { static struct sockaddr_un cli_addr,serv_addr; int i; int sockfd; int newsockfd; int clilen; int servlen; char recvline[256]; char c; char send[256]; if((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))< 0) printf("error socket\n"); serv_addr.sun_family=AF_UNIX; printf("le chemin est %s\n",argv[1]);// bcopy(argv[1],serv_addr.sun_path,strlen(a rgv[1])); servlen=strlen(serv_addr.sun_path) +sizeof(serv_addr.sun_family); if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) perror("bind"); clilen=sizeof(cli_addr); while(strcmp(send,"exit")!=0) { //reception du message recvfrom(sockfd,recvline,256,0,(struct sockaddr *)&cli_addr,&clilen); printf("\n\tClient : %s",recvline); if(strcmp(recvline,"exit")==0) break; //envoie du message

ii. Code client : Code Client.c :


#include<stdio.h> #include<stdlib.h> #include<sys/un.h> #include<sys/socket.h> #include<sys/types.h> #include<string.h> main(int argc,char *argv[]) { static struct sockaddr_un cli_addr,serv_addr; int i; int sockfd; int serlen; char sendline[256]; char recv[256]; int newsockfd; int clilen; if((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))< 0) printf("erreur creation de socket\n"); serv_addr.sun_family=AF_UNIX; bcopy(argv[1],serv_addr.sun_path,strlen(a rgv[1])); serlen=sizeof(serv_addr); while(strcmp(recv,"exit")!=0) { //envoie du message printf("\n\tClient : "); gets(sendline);

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 - Un serveur multiclients (Avec FORK()) :


4-1-Introduction : Un fork est une fonctionnalit sous les systmes UNIX ou Linux qui permet de dupliquer un processus. Pour expliquer son fonctionnement, on va partir d'un processus qu'on appellera avec affection "Le Papa". Ce processus va simplement se dupliquer et les deux processus (le pre et le fils) afficheront chacun leur statut (pre ou fils). Cette fonction va crer un processus. La valeur de retour n de cette fonction indique : n>0 On est dans le processus pre, n=0 On est dans le processus fils, n = -1 fork a chou, on n'a pas pu crer de processus. Voici un code C expliquant le fonctionnement du fork : Code C:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main () { pid_t pidf; //Initialis avec la fonction fork() pid_t pid = getpid(); //Obtenir PID du processus en cours

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);

write(newsockfd,sendline,sizeof(sendline)) ; }while(1); close(newsockfd);

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 }

} } //fermeture de la socket close(sockfd);

5- Un Serveur pour le transfert de fichiers :


5-1- Version TCP : 5-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> #include<string.h> #include<stdlib.h>

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 !");

ii. Code client : 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> main(int argc,char** argv) { FILE *f; char nom_fic[26]; int sockfd,servlen,max=50,n; struct sockaddr_in serv_addr; char sendline[256]; char recvline[256]; char recu[26]; serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr(argv [2]); serv_addr.sin_port=htons(atoi(argv[1])); if((sockfd=socket(AF_INET,SOCK_STREAM,0) )<0) printf("erreur creation de socket\n");

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)

if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0) printf("error connexion\n");

fwrite(recvline, 1, sizeof(recvline) , f); bzero(recvline,sizeof(recvline)); } printf("\t\t\nLecture et ecriture

14

termin \n"); fclose(f); } close(sockfd); }

Y); loc_addr.sin_port=htons(atoi(argv[1]));/ /ou htons(NUMPORT) printf("le numero de port est %s\n",argv[1]);

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)

ii. Code client : 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> main(int argc,char** argv) { FILE *f; char recu[26]; int sockfd,servlen; struct sockaddr_in serv_addr,cli_addr; char sendline[256]; char recvline[256]; 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])); if((sockfd=socket(AF_INET,SOCK_DGRAM,0))

fwrite(recvline,1, sizeof(recvline), f); } printf("\t\t\nLecture et ecriture termin \n"); fclose(f);

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); }

6- Un Serveur pour le transfert de fichiers multiclients (Avec FORK()) :


6-1- Version TCP : 6-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> #include <string.h> #include <signal.h> /*Pour gestion des signaux*/ #include <wait.h> /*Pour gestion des signaux*/ 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 i=0;//Compteur pour faire la diffrence entre les clients en leur donnant des numero 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]);

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

%d\n",p.login,j); printf("connexion\n"); CHAT: read(newsockfd,recvline,256); choix_2=atoi(recvline); switch(choix_2){ %s\n",p.login);

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;

7-2- code client :

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- ");

printf("\n\n\t\t Votre choix : "); scanf("%d",&choix); gets(ch); system("clear"); return choix;

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;

while(1){ choix=menu_1(); switch(choix){ case 1 :{ printf("\n\t\t 1-

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

printf("Connexion reussite \n"); CHAT: choix_2=menu_2(); switch(choix_2){

printf("\n\t\t Choix incorrect !"); break; }

22

QUITER- \n");

break; } case 3 :{ printf("\n\t\t 3-

write(sockfd,"2",sizeof("3")); exit(0); break; } default :{ printf("\n\t\t Votre choix est incorrecte ! \n"); break; } } } close(sockfd); }

23

Vous aimerez peut-être aussi