-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.c
More file actions
136 lines (108 loc) · 5.5 KB
/
Copy pathserver.c
File metadata and controls
136 lines (108 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv){
int sockfd, sockfd2; // descripteurs de socket
fd_set readfds; // ensemble des descripteurs en lecture qui seront surveilles par select
int t[FD_SETSIZE]; // tableau qui contiendra tous les descripteurs de sockets, avec une taille egale a la taille max de l'ensemble d'une structure fd_set
int taille=0; // nombre de descripteurs dans le tableau precedent
char buf[1024]; // espace necessaire pour stocker le message recu
memset(buf,'\0',1024); // initialisation du buffer qui sera utilisé
struct sockaddr_in my_addr; // structure d'adresse qui contiendra les param reseaux du recepteur
struct sockaddr_in client; // structure d'adresse qui contiendra les param reseaux de l'expediteur
// taille d'une structure sockaddr_in utile pour la fonction recvfrom
socklen_t sin_size = sizeof(struct sockaddr_in);
// verification du nombre d'arguments sur la ligne de commande
if(argc != 2){
printf("Usage: %s port_local\n", argv[0]);
exit(-1);
}
// creation de la socket
sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
// initialisation de la structure d'adresse du serveur (pg local)
// famille d'adresse
my_addr.sin_family = AF_INET;
// recuperation du port du serveur
my_addr.sin_port = ntohs(atoi(argv[1]));
// adresse IPv4 du serveur
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
// association de la socket et des param reseaux du serveur
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr)) != 0)
{
perror("Erreur lors de l'appel a bind -> ");
exit(1);
}
// indication de la limite MAX de la file d'attente des connexions entrantes
if(listen(sockfd,10) != 0)
{
perror("Erreur lors de l'appel a listen -> ");
exit(2);
}
printf("Attente de connexion\n");
t[0]=sockfd; // on ajoute deja la socket d'ecoute au tableau de descripteurs
taille++; // et donc on augmente "taille"
while(1){
FD_ZERO(&readfds); //il faut remettre tt les elements ds readfds a chaque recommencement de la boucle, vu que select modifie les ensembles
FD_SET(sockfd, &readfds); // ajoute le descripteur sockfd a l'ensemble readfs
int j;
int sockmax=0;
for(j=0;j<taille;j++)
{
if(t[j] != 0)
{
FD_SET(t[j],&readfds); // on remet donc tous les elements dans readfds
}
if(sockmax < t[j]) // et on prend ici le "numero" de socket maximal pour la fonction select
{
sockmax = t[j];
}
}
if(select(sockmax+1,&readfds,NULL,NULL,NULL) == -1)
{ // on utilise le select sur toutes les sockets y compris celle d'ecoute
perror("Erreur lors de l'appel a select -> ");
exit(1);
}
if(FD_ISSET(sockfd,&readfds))
{ // si la socket d'ecoute est dans readfds, alors qqch lui a ete envoye (=connection d'un client)
if((sockfd2 = accept(sockfd,(struct sockaddr*)&client,&sin_size)) == -1)
{ // on accepte la connexion entrante et on cree une socket...
perror("Erreur lors de accept -> ");
exit(3);
}
printf("Connexion etablie avec %s\n", inet_ntoa(client.sin_addr));
taille++; // ...qui est donc ajoutee au tableau de descripteurs
t[taille-1]=sockfd2;
}
int i;
for(i=1;i<taille;i++)
{ // on parcourt tous les autres descripteurs du tableau
if(FD_ISSET(t[i],&readfds))
{ // si une socket du tableau est dans readfds, alors qqch a ete envoye au serveur par un client
if(recv(t[i],&buf,1024,0) == -1)
{ // on stocke alors le message
perror("Erreur lors de la reception -> ");
exit(4);
}
printf("La chaine recue est: %s\n",buf);
int k;
for(k=1;k<taille;k++)
{ // puis on l'envoie a tous les clients...
if(k != i)
{ // ...sauf l'envoyeur
if(send(t[k],buf,1024,0) == -1)
{
perror("Erreur lors de l'appel a send -> ");
exit(1);
}
}
}
memset(buf,'\0',1024); // reinitialisation du buffer
}
}
}
}