Bonjour à tous,

Je viens vers vous, après moultes recherches, car je ne trouve pas la solution.
Je suis débutant en C et pour un projet de formation je dois faire un serveur TCP avec des threads, mais mon soucis c'est que je n'arrive pas à m'en sortir avec les fonctions recv() et send() qui me retourne sans cesse un bad file descriptor.
Je vous met le code serveur ( soyez indulgent )

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
182
183
184
185
186
187
188
// Nom: Serveur TCP/IP
 
#include <stdio.h>			// perror()
#include <netinet/in.h>		// sockaddr_in et INADDR_ANY
#include <sys/socket.h>		// socket(), bind(), recv(), send()
#include <sys/types.h>		// socket(), bind(), recv(), send(), wait()
#include <string.h>			// memset()
#include <signal.h>			// signal()
#include <wait.h>			// wait()
#include <pthread.h> 		// pour les thread
#include <stdlib.h>			// pour malloc()
 
// Pour open()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
// Definition des constantes symboliques
#define TAILLE_FILE_DATTENTE_CONNEXION 5 // Taille de la file d'attente de demandes de connexion
#define NUMERO_PORT_SERVEUR 30000
 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;		// Création du mutex
pthread_cond_t condition = PTHREAD_COND_INITIALIZER; 	// Création de la condition
 
// routine d'interception du signal SIGCHLD emis par les fils
void intercepterSignalSIGCHLD(int numeroSignalRecu);
 
// prototypes des fonctions
//int BougerRobot(int *socketConnectee);
static void *BougerRobot(void *socket);
static void *visualiser(void * argument);
 
int main()
{
	// couple adresse IP, numero de port serveur
	struct sockaddr_in coupleAdresseIPNumeroPortServeur;
 
	// couple adresse IP, numero de port client
	struct sockaddr_in coupleAdresseIPNumeroPortClient;
	int socketDemandeDeConnexion; // socket permettant d'effectuer une demande de connexion
	int socketConnectee; // socket dediee a une connexion etablie
	socklen_t longueurClient; // longueur du couple adresse IP, numero de port du client
	int optval;
 
	// Mise en place de l'interception de SIGCHLD emis par les fils
	signal(SIGCHLD,intercepterSignalSIGCHLD);
 
	// Initialiser les structures a des octets de valeurs
	memset(&coupleAdresseIPNumeroPortServeur,0,sizeof(struct sockaddr_in));
	memset(&coupleAdresseIPNumeroPortClient,0,sizeof(struct sockaddr_in));
 
	// Creer la socket serveur en mode TCP
	if ((socketDemandeDeConnexion = socket(PF_INET,SOCK_STREAM,0)) < 0)
	{
		perror("socket");
		return -1;
	}
 
	// Reutiliser le meme port en cas d'interruption brutal du serveur
	optval = 1;
	setsockopt(socketDemandeDeConnexion, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
 
	// Associer la socket serveur a un couple adresse IP, numero de port socket du domaine reseau
	coupleAdresseIPNumeroPortServeur.sin_family = AF_INET;
 
	// INADDR_ANY pour accepter les requetes de toutes les interfaces reseau du serveur
	coupleAdresseIPNumeroPortServeur.sin_addr.s_addr = htonl(INADDR_ANY);
 
	// affecter le numero de pott de l'application
	coupleAdresseIPNumeroPortServeur.sin_port = htons(NUMERO_PORT_SERVEUR);
	if (bind(socketDemandeDeConnexion,(struct sockaddr *)(&coupleAdresseIPNumeroPortServeur),sizeof(struct sockaddr_in)) < 0)
	{
		perror("bind");
		return -1;
	}
 
	// Creer une file d'attente de demandes de connexion
	if (listen(socketDemandeDeConnexion,TAILLE_FILE_DATTENTE_CONNEXION) <0)
	{
		perror("listen");
		return -1;
	}
	longueurClient = sizeof(struct sockaddr_in);
 
	// Création des variables de thread
	pthread_t idThreadBougerRobot; // Identifiant du thread bouger
	pthread_t idThreadVisualisation; // Identifiant du thread visualiser
 
	// Variables identification du client
	char idThread[2];
	int idT;
 
	while(1)
	{
		// Attendre une demande de connexion du client
		socketConnectee = accept(socketDemandeDeConnexion,(struct sockaddr *)(&coupleAdresseIPNumeroPortClient),&longueurClient);
		if (socketConnectee < 0)
		{
			perror ("accept");
		}
		else
		{
			idT = recv(socketConnectee, idThread, sizeof(idThread), 0);
			printf("Client: %d\n", idT);
			if(idT == 1)
			{
				// Créer le premier thread
				if (pthread_create (&idThreadBougerRobot, NULL, BougerRobot, (void *) &socketConnectee) != 0)
				{
					perror("pthread_create() bouger:");
					return -1;
				}
				// pthread_join(idThreadBougerRobot, NULL);
				printf("Thread bouger robot, créé.\n");
			}
			if (idT == 2)
			{
				// Créer le second thread
				if (pthread_create (&idThreadVisualisation, NULL, visualiser, NULL) != 0)
				{
					perror("pthread_create() afficher:");
					return -1;
				}
				printf("Thread visualisation unity, créé.\n");
			}
 
			// dans le pere fermer dans le pere la socket connectee
			if(close(socketConnectee) < 0)
			{
				perror("close");
				return -1;
			}
		}
	}
	return 0;
}
 
void intercepterSignalSIGCHLD(int numeroSignalRecu)
{
	wait(NULL);
}
 
static void *BougerRobot(void *socket)
{
	char lettre;
	char *lettreReponse;
	int pvsocket = *(int *) socket;
	printf("%d\n", pvsocket);
 
	// Recevoir la requête
	if (recv(pvsocket, &lettre, sizeof(lettre), 0) == -1)
	{
		perror("recvfrom");
	}
 
	// Traiter la requete
	*lettreReponse = lettre + 1;
	printf("%c\n", *lettreReponse);
 
	// Envoyer la réponse
	if (send(pvsocket, &lettreReponse, sizeof(lettreReponse), 0) == -1)
	{
		perror("sendto");
	}
 
}
 
static void *visualiser(void * argument)
{
	int compteur = 0, nombre = 0;
    srand(time(NULL));
 
    while(1) /* Boucle infinie */
    {
        nombre = rand()%10; /* On tire un nombre entre 0 et 10 */
        compteur += nombre; /* On ajoute ce nombre à la variable compteur */
        printf("\n%d", compteur);
        if(compteur >= 20) /* Si compteur est plus grand ou égal à 20 */
        {
            pthread_mutex_lock (&mutex); /* On verrouille le mutex */
            pthread_cond_signal (&condition); /* On délivre le signal : condition remplie */
            pthread_mutex_unlock (&mutex); /* On déverrouille le mutex */
            compteur = 0; /* On remet la variable compteur à 0 */
        }
        sleep (1); /* On laisse 1 seconde de repos */
    }
    pthread_exit(NULL); /* Fin du thread */
}

Voici le code client qui utilise le thread pour le changement de lettre ( c'est un exercice, ça n'a pas grand intérêt ) :
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
// clientMinimumTcp.c
// envoie une lettre au serveur et reçoit la lettre suivante dans l'alphabet
// clientMinimumTcp <adresse_IP_serveur>
// clientMinimumTcp 192.168.10.1
 
#include <stdio.h>			// perror(), printf(), fprintf(), scanf() 
#include <arpa/inet.h>		// inet_pton(), htons()
#include <sys/socket.h>		// socket(), recv(), send(), connect()
#include <sys/types.h>		// socket(), recv(), send(), connect()
#include <string.h>			// memset() 
 
#define NUMERO_PORT_SERVEUR 30000
 
int main(int argc, char * argv[])
{
	int i = 1;
 
	/* couple adresse IP, numero de port serveur */
	struct sockaddr_in coupleAdresseIPNumeroPortServeur;
	int socketClient; /* socket client */
	int longueurReponse; /* longueur de la reponse recue */
	socklen_t longueurServeur; /* longueur du couple adresse IP, numero de port	du serveur */
	long int adresseIPServeur; /* adresse IP du Serveur */
	char lettre, lettreReponse;
 
	/* Tester le nombre d'arguments */
	if (argc != 2)
	{
		fprintf(stderr,"usage : clientMinimumTcp <adresse_IP_serveur>\nexemple : clientMinimumTcp 192.168.10.1\n");
		return -1;
	}
 
	/* Initialiser les structures a des octets de valeurs */
	memset(&coupleAdresseIPNumeroPortServeur,0,sizeof(struct sockaddr_in));
 
	/* Initialiser l'adresse IP et le numero de port du serveur */
	/* adresse IP au format reseau */
	if (inet_pton(AF_INET, argv[1], (void *)&adresseIPServeur) < 0)
	{
		perror("inet_pton");
		return -1;
	}
 
	/* socket du domaine reseau */
	coupleAdresseIPNumeroPortServeur.sin_family = AF_INET;
 
	/* adresse IP */
	coupleAdresseIPNumeroPortServeur.sin_addr.s_addr = adresseIPServeur;
 
	/* affecter le numero de port de l'application */
	coupleAdresseIPNumeroPortServeur.sin_port = htons(NUMERO_PORT_SERVEUR);
 
	/* Creer la socket client en mode TCP */
	if ((socketClient = socket(PF_INET,SOCK_STREAM,0)) < 0)
	{
		perror("socket");
		return -1;
	}
 
	/* Effectuer une demande de connexion */
	longueurServeur = sizeof(struct sockaddr_in);
	if (connect(socketClient, (struct sockaddr *)&coupleAdresseIPNumeroPortServeur,	longueurServeur) < 0)
	{
		perror("connect");
		return -1;
	}
 
	// Envoyer la requete identification client
	char connectionClient[1] = "c";
	if (send(socketClient, &connectionClient, sizeof(connectionClient), 0) == -1)
	{
		perror("sendto");
		return -1;
	}
 
	// Boucle de requêtes
	for ( i ; i <= 10 ; i++)
	{
		/* demander à l'utilisateur de formuler une requete */
		printf("Entrez une lettre :");
		scanf("%c",&lettre);
 
		/* Envoyer la requete */
		if (send(socketClient, &lettre, sizeof(lettre), 0) == -1)
		{
			perror("sendto");
			return -1;
		}
 
		/* Recevoir la reponse */
		if (recv(socketClient,&lettreReponse, sizeof(unsigned char),0) == -1)
		{
			perror("recvfrom");
			return -1;
		}
 
		/* Afficher la reponse */
		printf("J'ai émis : %c, j'ai reçu : %c\n",lettre, lettreReponse);
		fgetc(stdin); // On vide le cache mémoire
	}
 
	/* Fermer la connexion */
	if (close(socketClient) < 0)
	{
		perror("close");
		return -1;
	}
	return 0;
}

Merci pour votre aide car je deviens