Bonjour

alors ça fait un moment que je bosse sur un chat et j'ai un problème étrange que je n'arrive pas à résoudre.
En effet au bout d'un certain nombre de messages échangés entre les deux clients, le premier client à avoir été connecté au serveur n'arrive plus à envoyer des messages. Le serveur ne les perçoit plus. Mais il arrivent parfois que celui-ci (bien que le serveur ne reçoive plus ses messages) puisse recevoir ceux du client2.

C'est un peu dure à expliquer, car des fois ça varie, ou après seulement un message du client2 il est impossible de rentrer en communication avec le serveur (j'ai l'impression) comme dans le teste ci-dessous.

Une photo du dernier teste si ça peut vous aider à visualiser

Image ici

Une autre avec le même bug (cas le plus souvent rencontré) le serveur n'a pas reçue le dernier message de clientA, donc bibi non plus. La connexion entre ClientA et le serveur est donc apparemment inexistante à ce moment

ICI

Source :

Serveur :
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
 
#if defined (WIN32)
    #include <winsock2.h>
    typedef int socklen_t;
#elif defined (linux)
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define INVALID_SOCKET -1
    #define SOCKET_ERROR -1
    #define closesocket(s) close(s)
    typedef int SOCKET;
    typedef struct sockaddr_in SOCKADDR_IN;
    typedef struct sockaddr SOCKADDR;
#endif
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <string.h>
#define CLIENT_MAX 1000
 
const char * NomJourSemaine[] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"};
const char * NomMois[] = {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"};
 
/*--------------PASSWD----------------------------*/
static void purger(void)
{
    int c;
 
    while ((c = getchar()) != '\n' && c != EOF)
    {}
}
 
static void clean (char *passwd)
{
    char *p = strchr(passwd, '\n');
 
    if (p)
    {
        *p = 0;
    }
 
    else
    {
        purger();
    }
}
/*------------------PASSWD------------------------------*/
/*--------------PORT-----------------------------------*/
static void purgerA(void)
{
    int d;
 
    while ((d = getchar()) != '\n' && d != EOF)
    {}
}
 
static void cleanA (char *addr_port)
{
    char *q = strchr(addr_port, '\n');
 
    if (q)
    {
        *q = 0;
    }
 
    else
    {
        purgerA();
    }
}
/*------------------PORT-----------------------------------*/
 
typedef struct _Local
{
SOCKET s_server;
SOCKET s_client;
} Local;
 
void * readAndSend(void * inform); // Fonction pour recevoire et renvoyer les messages des clients
 
SOCKET s_global[CLIENT_MAX];
int index_s = 0;
 
int main(void)
{
  #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #else
        int erreur = 0;
    #endif
 
  Local * inform; 
  inform = malloc (sizeof(Local)); 
  char passwd[40];
  char addr_port[20];
  long int port = 0;
  char* fin = NULL;
 
  printf("Sur quelle port utilisez-vous ce serveur : ");
  fgets(addr_port, sizeof addr_port, stdin);
  cleanA(addr_port);
  port = strtol(addr_port, &fin, 10);
  printf("le port enregistr\x82 est le %ld", port);
 
  printf("\n\nEntrez le mot de passe d\x82sir\x82 pour le serveur : ");
  fgets(passwd, sizeof passwd, stdin);
  clean(passwd);
  printf("Le mot de passe enregistr\x82 est : %s\n", passwd);
  printf("\n\nSi celui-ci ne vous convient pas, vous pouvez le changer en red\x82marrant\n \ble serveur.\n");
  printf("\n\n\nServeur en cour de fonctionnement !\n");
 
 inform->s_server;
 
        inform->s_server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
        if (inform->s_server == INVALID_SOCKET)
	       {
            printf("La fonction socket a \x82 \bchou\x82.\n");
            getchar();
	       }
 
        else
        {
            SOCKADDR_IN server;
 
            server.sin_family       = AF_INET;
            server.sin_addr.s_addr  = htonl(INADDR_ANY);
            server.sin_port         = htons(port);
            memset(&server.sin_zero, '\0', sizeof(server.sin_zero));
 
            if (bind(inform->s_server, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
		       {
                printf("La fonction bind a \x82 \bchou\x82.\n");
                getchar();
		       }
 
         else
           {
 
		        char buffer[100];
                int n;
 
	      while(1)
	        { // Boucle pour accepter un Client.
                if (listen(inform->s_server, 0) == SOCKET_ERROR)
	              {
		           printf("la fonction listen a \x82 \bchou\x82.\n");
	              }
 
                else
                {
                    inform->s_client;
                    SOCKADDR_IN client;
                    socklen_t csize = sizeof(client);
 
                    inform->s_client = accept(inform->s_server, (SOCKADDR *)&client, &csize);
                    s_global[index_s++] = inform->s_client; 
                    if (inform->s_client == INVALID_SOCKET)
			          {
                         printf("La fonction accept a \x82 \bchou\x82.\n");
		              }
 
                    else
                    {                        
 
                        printf("Le client %s s'est connect\x82 !\n", inet_ntoa(client.sin_addr));
						send(inform->s_client, passwd, (int)strlen(passwd), 0);
			            pthread_t thread; // Thread pour gérer les messages des clients en même temps que la fonction main afin de permettre à d'autre clients de se connecter sans bloquer les communication.
                        pthread_create(&thread, NULL, (void*)readAndSend, inform); 
		            }			  
			    }		
	        }
           }
        }
 
    return 0;
}						  
 
 
 
void * readAndSend(void * inform)
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
Local * in = (Local *) inform;
 
char buffer[1024];
char buff[1024];
int n;
 
    while (1) 
    { // boucle de reception et d'envoie des messages.
	time_t timestamp;
	struct tm * t;
 
	timestamp = time(NULL);
	t = localtime(&timestamp);	
 
        memset(buffer, '\0', sizeof(buffer));
        n = recv(in->s_client, buffer, sizeof(buffer) - 1, 0); 
 
	if (n > 0)
	{ // si on reçoie se que le client dit
	buffer[n] = '\0';
	printf("%02u/%s/%04u at ", t->tm_mday, NomMois[t->tm_mon], 1900 + t->tm_year);
	printf("%02u:%02u:%02u -> ", t->tm_hour, t->tm_min, t->tm_sec);
        printf("%s\n", buffer);    		
        sprintf(buff, "%s", buffer);  
 
        int i;
        for (i = 0; i < index_s; i++)
        {
            send (s_global[i], buff, (int)strlen(buff), 0); 
        }   
	}
 
	else
	{ // dnas le cas où un client se déconnecte. On ne recoie rien
	closesocket(in->s_client); // on ferme sa socket
	printf("La fonction recv a \x82 \bchou\x82.\n");
    pthread_exit(NULL); // et on ferme son thread. 
	break;
	}	
 
    }
return NULL;
}
Désolé pour l'indentation du code