Bonjour,
Je programme deux applications : le client et le serveur. Ils se connectent en TCP. Lors de la première connexion il n'y a pas de problème, ils communiquent correctement. Mais lorsque je relance l'application, j'obtiens le message d'erreur suivant :
client.c :bind(sock, (struct sockaddr *) &serveur_adr, sizeof(struct sockaddr_in)): Address already in use
serveur.c :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 #include "client.h" key_t cleMemoirePartagee = 4049; key_t cleSemaphoresPartagee = 4149; int portServeur = 4255; int sock; char buffer[TAILLE_BUFFER]; int main(int argc, char** argv) { char * ip = "127.0.0.1"; char * nomJoueur = "alex"; demarrePartie(ip, portServeur, nomJoueur); terminePartie(); } int demarrePartie(char * ip, int port, char * nomJoueur) { struct sigaction act; act.sa_handler=sig_handler; act.sa_flags=0; SYS(sigaction(SIGINT,&act,NULL)); struct sockaddr_in sock_host; // Ouverture d'un socket SYS(sock = socket(AF_INET, SOCK_STREAM, 0)); // Création de l'ip du serveur memset(& sock_host, '\0', sizeof(sock_host)); sock_host.sin_family = AF_INET; sock_host.sin_port = htons(port); if (inet_aton(ip, & sock_host.sin_addr) == 0) { perror("Erreur"); libereMemoire(); exit(EXIT_FAILURE); } // Demande de connexion au serveur SYS(connect(sock, (struct sockaddr *) &sock_host, sizeof(sock_host))); struct timeval timeout; timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; // Envoie du nom du joueur au serveur MessageSocketChaine nomJoueurSend; memcpy(nomJoueurSend.messageChar, nomJoueur, strlen(nomJoueur)+1); if (!envoyerMessageTimeout(sock, &nomJoueurSend, sizeof(MessageSocketChaine), &timeout)) //if (!ecris(sock, nomJoueur, sizeof(MessageSocketChaine), &timeout)) { printf("Impossible de joindre le serveur."); exit(EXIT_FAILURE); } // Réception clés timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; int nbOctRecus; if (!(nbOctRecus = recevoirMessageTimeout(sock, buffer, sizeof(MessageSocketInteger), &timeout))) //if (!(nbOctRecus = lisServeur(sock, buffer, sizeof(MessageSocketInteger), &timeout))) { printf("Impossible de joindre le serveur."); exit(EXIT_FAILURE); } cleMemoirePartagee = ((MessageSocketInteger *) buffer)->message; timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; if (!(nbOctRecus = recevoirMessageTimeout(sock, buffer, sizeof(MessageSocketInteger), &timeout))) //if (!(nbOctRecus = lisServeur(sock, buffer, sizeof(MessageSocketInteger), &timeout))) { printf("Impossible de joindre le serveur."); exit(EXIT_FAILURE); } cleSemaphoresPartagee = ((MessageSocketInteger *) buffer)->message; // Récupération du message de commencement timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; if (!(nbOctRecus = recevoirMessageTimeout(sock, buffer, sizeof(MessageSocketChaine), &timeout))) //if (!(nbOctRecus = lisServeur(sock, buffer, sizeof(MessageSocketChaine), &timeout))) { printf("Impossible de joindre le serveur."); exit(EXIT_FAILURE); } printf("%s\n", ((MessageSocketChaine *) buffer)->messageChar); creeAccesMemoireCommune(cleMemoirePartagee, cleSemaphoresPartagee); return 0; } int terminePartie() { libereResources(); return 0; } void libereResources() { close(sock); } void sig_handler(int signal) { switch(signal){ case SIGINT: libereResources(); exit(1); default: break; } }
J'ai remarqué qu'en créant une connexion avec le client sans lui envoyer d'information, c'est à dire en cachant les lignes :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 #include "serveur.h" const key_t CLE_MEMOIRE_PARTAGEE = 4049; const key_t CLE_SEMAPHORES = 4149; int portServeur = 4255; int nombreJoueursConnectes = 0; char buffer[TAILLE_BUFFER]; static Joueur * joueursConnectes[MAX_JOUEURS]; int main(int argc, char** argv) { printf("serveur\n"); //SIGACTION struct sigaction act; act.sa_handler=sig_handler; act.sa_flags=0; SYS(sigaction(SIGINT,&act,NULL)); //StructurePartagee * test; //test = creeMemoireCommune(CLE_MEMOIRE_PARTAGEE, CLE_SEMAPHORES); attenteConnexions(); terminePartie(); return 0; } int attenteConnexions() { //Gestion des 30secondes time_t timestamp1 = time(NULL); time_t timestamp2 = time(NULL); //Création du socket int sock; SYS(sock = socket(AF_INET, SOCK_STREAM, 0)); //Création de l'interface struct sockaddr_in serveur_adr; memset(&serveur_adr, '\0', sizeof(serveur_adr)); //Création adresse serveur serveur_adr.sin_family = AF_INET; serveur_adr.sin_port = htons(portServeur); serveur_adr.sin_addr.s_addr = htonl(INADDR_ANY); //On accepte n'importe quelle adresse //Association de l'adresse locale au socket SYS(bind(sock, (struct sockaddr *) &serveur_adr, sizeof(struct sockaddr_in))); //Attente connexions SYS(listen(sock, MAX_JOUEURS)); // //fd_set readfs; // while (nombreJoueursConnectes < MAX_JOUEURS && difftime(timestamp2, timestamp1) < 10) { struct timeval timeout; timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; /* struct timeval tempsAttenteConnexions; tempsAttenteConnexions.tv_sec = 5; tempsAttenteConnexions.tv_usec = 0; FD_ZERO(&readfs); FD_SET(sock, &readfs); int ret; SYS(ret = select(sock+1,&readfs, NULL, NULL, &tempsAttenteConnexions)); if(ret == 0 && nombreJoueursConnectes >= MIN_JOUEURS) break; if(FD_ISSET(sock, &readfs)) { */ struct sockaddr_in addresseClient; int tailleAdresseClient = sizeof(addresseClient); int socketClient; SYS(socketClient = accept(sock, (struct sockaddr *) &addresseClient, &tailleAdresseClient)); // Lecture du nom du joueur int nbCharsLu; if ((nbCharsLu = recevoirMessageTimeout(socketClient, buffer, sizeof(MessageSocketChaine), &timeout)) == 0) break; char * nomJoueur = ((MessageSocketChaine *) buffer)->messageChar; nomJoueur[nbCharsLu] = '\0'; // Création du joueur Joueur * joueur = malloc(sizeof(Joueur)); joueur->nom = nomJoueur; joueur->socket = socketClient; joueursConnectes[nombreJoueursConnectes] = joueur; nombreJoueursConnectes++; fprintf(stderr, "Le joueur %s s'est connecté.\n", joueur->nom); timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; // Envoie des clés de la mémoire partagée et sémaphores au client MessageSocketInteger messageCleMemoire = {INTEGER_TYPE_DONNEE, CLE_MEMOIRE_PARTAGEE}; if (!envoyerMessageTimeout(joueur->socket, &messageCleMemoire, sizeof(MessageSocketInteger), &timeout)) { supprimerJoueur(nombreJoueursConnectes-1); fprintf(stderr, "messageCleMemoire\n"); break; } timeout.tv_sec = TIME_OUT; timeout.tv_usec = 0; MessageSocketInteger messageCleSemapores = {INTEGER_TYPE_DONNEE, CLE_SEMAPHORES}; if (!envoyerMessageTimeout(joueur->socket, &messageCleSemapores, sizeof(MessageSocketInteger), &timeout)) { supprimerJoueur(nombreJoueursConnectes-1); fprintf(stderr, "messageCleSemapores\n"); break; } //Gestion des 30secondes timestamp2 = time(NULL); fprintf(stderr, "%e\n", difftime(timestamp2, timestamp1)); //} } SYS(close(sock)); return 0; } void supprimerJoueur(int iJoueur) { fprintf(stderr, "Joueur %s ne répond plus.\n", joueursConnectes[iJoueur]->nom); int i; for(i = iJoueur; i < (nombreJoueursConnectes-1); i++) joueursConnectes[i] = joueursConnectes[i+1]; nombreJoueursConnectes--; //manquementJoueurs(); } void terminePartie() { //Annonce vainqueur libereResources(); } void libereResources() { int i; for (i=0; i < nombreJoueursConnectes; i++) { fprintf(stderr, "libereResources() : %d\n", i); SYS(close(joueursConnectes[i]->socket)); free(joueursConnectes[i]); } libereMemoire(); } void sig_handler(int signal) { switch(signal) { case SIGINT: libereResources(); exit(1); default: break; } }
par le code qui suit, je n'ai plus aucun problème de bind au démarrage suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if ((nbCharsLu = recevoirMessageTimeout(socketClient, buffer, sizeof(MessageSocketChaine), &timeout)) == 0) break; char * nomJoueur = ((MessageSocketChaine *) buffer)->messageChar; nomJoueur[nbCharsLu] = '\0';
Voici le code des deux méthodes que j'ai créé pour recevoir et envoyer des messages :
Code : Sélectionner tout - Visualiser dans une fenêtre à part char * nomJoueur = "Fred";
D'avance merci pour vos réponses.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 int recevoirMessageTimeout(int socket, void * buff, size_t buffL, struct timeval * timeout) { int taille; if ((taille = recv(socket, buff, buffL, 0)) < 0) { perror("recv()"); return 1; } return taille; } int envoyerMessageTimeout(int socket, void * buff, size_t buffL, struct timeval * timeout) { int taille = 0; if ((taille = send(socket, buff, buffL - 1, 0)) < 0) { perror("send()"); //if recv error we disonnect the client taille = 0; } return taille; }
xenos
Partager