Bonjour à tous,
Actuellement en train d'essayer de comprendre les sockets via le langage C sous Linux ( échange des données à travers une connexion socket), j'ai d'abord créé un fichier serveur.c qui prend en argument le numéro de port d’écoute et, en option, l’adresse IPv4 d’écoute et un fichier client.c qui prend en argument le numéro de port et l’adresse IPv4 du serveur.
Pour l'instant, lpour essayer de mieux comprendre, le serveur ne sert qu’un seul client et se termine avec la fin de la connexion. Le client envoie toutes les trente secondes au serveur une demande d’état. Le serveur répond en
fournissant son PID. Le client se termine sur réception d’un signal.
Seulement, quand je lance en premier le serveur, j'ai bien ce dernier qui est à l'écoute :
Je lance ensuite le client :
Mais immédiatement côté serveur, la connexion se ferme et j'ai le message "read: Bad file descriptor"
Pourriez-vous me dire où ça pêche dans le code car je ne vois pas ?
D'avance merci.
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 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <signal.h> #include <arpa/inet.h> #include <time.h> // Ajouter cette ligne pour utiliser la fonction time() // Fonction pour la création d'un socket client int creer_socket_client(const char* adresse_ip, int port) { int socket_client; // Numéro de la socket client struct sockaddr_in adresse_serveur; // Adresse du serveur // Création de la socket socket_client = socket(AF_INET, SOCK_STREAM, 0); if (socket_client == -1) { perror("socket client"); exit(-1); } // Configuration de la socket adresse_serveur.sin_family = AF_INET; // Protocole de la socket (IP) adresse_serveur.sin_port = htons(port); // Numéro de port du serveur inet_aton(adresse_ip, &adresse_serveur.sin_addr); // Adresse IP du serveur // Connexion au serveur if (connect(socket_client, (struct sockaddr*)&adresse_serveur, sizeof(adresse_serveur)) == -1) { perror("connect"); exit(-1); } return socket_client; } // Fonction pour faire dormir le programme pendant un certain nombre de secondes // en affichant un compte à rebours à l'écran void sleep_with_countdown(int seconds) { // Afficher un message indiquant que le client est en attente pendant le nombre de secondes spécifié printf("En attente pendant %d secondes...\n", seconds); // Définir le temps de départ time_t start = time(NULL); // Répéter jusqu'à ce que le nombre de secondes spécifié soit écoulé while (time(NULL) - start < seconds) { // Calculer le temps restant en secondes int remaining = seconds - (time(NULL) - start); // Afficher le temps restant sur la ligne précédente printf("Temps restant : %d secondes", remaining); // Dormir pendant 1 seconde sleep(1); } } int main(int argc, char* argv[]) { int socket_client; // Numéro de la socket client int port; // Numéro de port du serveur char* adresse_ip; // Adresse IP du serveur char buffer[32]; // Buffer pour stocker la réponse du serveur // Vérifier le nombre d'arguments if (argc != 3) { printf("Usage: %s adresse_ip port\n", argv[0]); exit(-1); } // Récupérer l'adresse IP et le numéro de port adresse_ip = argv[1]; port = atoi(argv[2]); // Créer la socket client socket_client = creer_socket_client(adresse_ip, port); // Afficher un message indiquant que la connexion avec le serveur est établie printf("Connexion avec le serveur établie...\n"); // BOUCLE PRINCIPALE while (1) { // Envoyer une demande d'état au serveur write(socket_client, "ETAT", strlen("ETAT") + 1); // Afficher un message indiquant que la demande d'état a été envoyée printf("Demande d'état envoyée...\n"); // Afficher un message indiquant que le client est en train d'attendre la réponse du serveur printf("En attente de la réponse du serveur...\n"); // Attendre la réponse du serveur if (read(socket_client, buffer, sizeof(buffer)) == -1) { perror("read"); exit(-1); } // Afficher la réponse du serveur (son PID) printf("Réponse du serveur : %s\n", buffer); // Utiliser la fonction sleep_with_countdown() pour afficher un compte à rebours de 30 secondes // avant de continuer avec la boucle sleep_with_countdown(30); } // Fermer la socket client close(socket_client); return 0; }
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 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> // Fonction pour la création d'un socket serveur int creer_socket_serveur(int port) { int socket_serveur; int optval = 1; struct sockaddr_in adresse_locale; char adresse_ip[INET_ADDRSTRLEN]; // Création de la socket socket_serveur = socket(AF_INET, SOCK_STREAM, 0); if (socket_serveur == -1) { perror("socket serveur"); exit(-1); } // On rend le port réutilisable rapidement après un arrêt brutal if (setsockopt(socket_serveur, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) == -1) { perror("setsockopt"); exit(-1); } // Configuration de la socket adresse_locale.sin_family = AF_INET; adresse_locale.sin_port = htons(port); adresse_locale.sin_addr.s_addr = INADDR_ANY; if (bind(socket_serveur, (struct sockaddr*)&adresse_locale, sizeof(adresse_locale)) == -1) { perror("bind serveur"); exit(-1); } // Afficher l'adresse IP d'écoute choisie par défaut if (inet_ntop(AF_INET, &adresse_locale.sin_addr, adresse_ip, INET_ADDRSTRLEN) == NULL) { perror("inet_ntop"); exit(-1); } printf("Adresse IP d'écoute : %s\n", adresse_ip); // Afficher le port d'écoute choisi par défaut port = ntohs(adresse_locale.sin_port); printf("Port d'écoute : %d\n", port); // Démarrage du listage if (listen(socket_serveur, 10) == -1) { perror("listen serveur"); exit(-1); } return socket_serveur; } int main(int argc, char* argv[]) { int socket_serveur; int socket_client; int port; socklen_t longueur_adresse_courante; struct sockaddr_in adresse_client_courant; char buffer[32]; // Vérifier le nombre d'arguments if (argc != 2) { printf("Usage: %s port\n", argv[0]); exit(-1); } // Récupérer le numéro de port port = atoi(argv[1]); // Créer la socket serveur socket_serveur = creer_socket_serveur(port); // Afficher un message indiquant que le serveur est en écoute printf("Le serveur est en écoute sur le port %d...\n", port); // BOUCLE PRINCIPALE while (1) { // Attendre une connexion client longueur_adresse_courante = sizeof(adresse_client_courant); socket_client = accept(socket_serveur, (struct sockaddr*)&adresse_client_courant, &longueur_adresse_courante); if (socket_client == -1) { perror("accept"); exit(-1); } // Afficher un message indiquant qu'un client s'est connecté printf("Un client s'est connecté...\n"); // BOUCLE DE TRAITEMENT while (1) { // Lire la demande du client if (read(socket_client, buffer, sizeof(buffer)) == -1) { perror("read"); exit(-1); } // Vérifier si c'est une demande d'état if (strcmp(buffer, "ETAT") == 0) { // Répondre en envoyant le PID du serveur sprintf(buffer, "%d", getpid()); write(socket_client, buffer, strlen(buffer) + 1); } else { // Sinon, ignorer la demande } // Fermer la socket client close(socket_client); // Afficher un message indiquant que la connexion avec le client est fermée printf("Connexion avec le client fermée.\n"); } } // Fermer la socket serveur close(socket_serveur); return 0; }
Partager