Salut a tous!

Voila j'ai un jeu en reseau.
Dans ce jeu, j'ai 2 threads qui ouvre des connexions TCP :
- Un qui ne fait que des boucles avec un recv pour recevoir la position du client.
- L'autre qui ne fait que des boucles avec un send pour envoyer sa position à l'autre.

Ce que j'aimerai faire, c'est que quand quelqu'un ferme sa fenetre, ou en fin de partie, bref quand on veut terminer le jeu, cela me ferme proprement :
- le socket de reception de mon PC
- le socket d'envoi de mon PC
- le socket de reception du PC distant
- le socket d'envoi du PC distant.

Pour cela dans la structure envoyée a mon thread (et échangée sur le réseau) j'ai intégré une variable "ActiverTransmission".
Quand je veux fermer la connexion, mon application principale fait passer cette variable à 0.
Ce qui a pour effet, dans mon thread d'emission, d'envoyer un shutdown de la connexion dans les 2 sens.
La variable recevant le code d'erreur du shutdown s'appelle ActiverBoucle, et elle passe a 0 quand le shutdown reussi, ce qui a donc en plus pour effet de sortir de ma boucle de transmission, et de passer au reste du code pour fermer proprement la socket.

Le problème :
Sur mon PC j'ouvre mon application une premiere fois afin de simuler un joueur. Je l'appelle "hebergeur"
J'ouvre une deuxieme fois une copie de mon application (la meme mais configurée specialement pour se connecter à la premiere) je l'appelle "client"

Lorsque je ferme mon "client", j'ai une erreur qui apparait sur mon "hebergeur" :
Impossible de recevoir les données (donc du a mon recv) avec le code d'erreur WSA 10054 qui signifie WSAECONNRESET (10054) Connection reset by peer.

Bizarre, car mon client a donc envoyé un shutdown qui a visiblement mal été interprété par mon "hebergeur"

Pouvez vous m'aider ???

Voici le code :

La structure envoyée a mon thread :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
typedef struct StructSocket
{
    SDL_Rect PositionJoueur;
    char IPUtilisee[16];
    char PortUtilise[6];
    SOCKET IDSocketServeur;
    SOCKET IDSocketClient;
    BOOL ActiverTransmission;
} StructSocket;
Mon thread de reception :
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
DWORD WINAPI ThreadReception(void * infRecpt) // Avec un thread on a un type void * (on peut mettre ce qu'on veut)
{
      StructSocket * SocketReception = infRecpt; // On indique qu'on veut travailler sur une structure InfosPartie pour notre variable e/s
      StructSocket VarTempReception;
      int CodeErreur; // Code d'erreur des fonctions
      int TailleConfigClient;
      int PortEcoute;
      char TexteErreur[120]; // Pour insérer le message d'erreur des socket dans la msgbox
      int LongueurMessage=1; // Nombre de caracteres
      SOCKADDR_IN ConfigServeur,ConfigClient; // Structure contenant les infos du serveur
 
      SocketReception->IDSocketServeur = socket(AF_INET,SOCK_STREAM,0); // On ouvre la socket en UDP
      if (SocketReception->IDSocketServeur == INVALID_SOCKET)
      {
               sprintf(TexteErreur,"Impossible de creer la socket du à l'erreur : %d",WSAGetLastError());
               MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
               return -1; // On termine la fonction et renvoi -1 pour prevenir l'appli principale
      }
 
 
      /* Config Infos Serveur */  
      ConfigServeur.sin_family = AF_INET;
      ConfigServeur.sin_addr.s_addr = inet_addr(SocketReception->IPUtilisee); 
      sscanf(SocketReception->PortUtilise, "%d", &PortEcoute); // On reconverti notre port de char vers int
 
      #ifdef _UTILISATIONLOCALE_
      #if TYPEJOUEUR == 1
      ConfigServeur.sin_port = htons(2222);
      #else
      ConfigServeur.sin_port = htons(2223);
      #endif
 
      #else
      ConfigServeur.sin_port = htons(PortEcoute);
      #endif
      /* ******************* */
 
      CodeErreur = bind(SocketReception->IDSocketServeur,(struct sockaddr*)&ConfigServeur,sizeof(ConfigServeur)); // On bind la socket
      if (CodeErreur != 0)
      {
            sprintf(TexteErreur,"Impossible de binder la socket du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            return -1;
      }
 
      CodeErreur = listen(SocketReception->IDSocketServeur, 1);
      if (CodeErreur != 0)
      {
            sprintf(TexteErreur,"Impossible d'écouter la socket du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            closesocket(SocketReception->IDSocketServeur);
            return -1;
      }
 
      TailleConfigClient = sizeof(ConfigClient);
      SocketReception->IDSocketClient = accept(SocketReception->IDSocketServeur, (struct sockaddr*)&ConfigClient, &TailleConfigClient);
 
      if (SocketReception->IDSocketClient == INVALID_SOCKET)
      {
            sprintf(TexteErreur,"Impossible de recuperer la socket client du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            closesocket(SocketReception->IDSocketServeur);
            return -1; // On termine la fonction et renvoi -1 pour prevenir l'appli principale
      }
 
      do
      {
            LongueurMessage = recv(SocketReception->IDSocketClient, (char*)&VarTempReception, sizeof(StructSocket),0); // On recoit et on reboucle
            if (LongueurMessage == SOCKET_ERROR)
            {
                 sprintf(TexteErreur,"c: Impossible de recevoir les données du à l'erreur : %d",WSAGetLastError());
                 MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                 closesocket(SocketReception->IDSocketServeur);
                 closesocket(SocketReception->IDSocketClient);
                 return -1;
            }
 
            SocketReception->PositionJoueur = VarTempReception.PositionJoueur;
 
      } while (LongueurMessage != 0); // LongueurMessage vaut 0 si on recoit un shutdown, on ferme donc proprement les sockets apres.
 
 
 
      CodeErreur = closesocket(SocketReception->IDSocketServeur); // On ferme la socket qui a été ouverte
      if (CodeErreur != 0)
      {
            sprintf(TexteErreur,"Impossible de libérer la socket serveur du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            return -1;
      }
      CodeErreur = closesocket(SocketReception->IDSocketClient); // On ferme la socket qui a été ouverte
      if (CodeErreur != 0)
      {
            sprintf(TexteErreur,"Impossible de libérer la socket client du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            return -1;
      }
 
      return 0;
 
}
Mon thread d'envoi :
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
DWORD WINAPI ThreadTransmission(void * infTrans) // Avec un thread on a un type void * (on peut mettre ce qu'on veut)
{
      StructSocket * SocketTransmission = infTrans; // On indique qu'on veut travailler sur une structure InfosPartie pour notre variable e/s
      int CodeErreur; // Code d'erreur des fonctions
      int TailleConfigClient;
      int PortEcoute;
      int ActiverBoucle=1; // Cette variable passe à 0 lors d'un shutdown
      char TexteErreur[120]; // Pour insérer le message d'erreur des socket dans la msgbox
      int LongueurMessage; // Nombre de caracteres
      SOCKADDR_IN ConfigServeur,ConfigClient; // Structure contenant les infos du serveur
      SDL_Rect PositionJLocalPrecedente;
 
      SocketTransmission->IDSocketServeur = socket(AF_INET,SOCK_STREAM,0); // On ouvre la socket en UDP
      if (SocketTransmission->IDSocketServeur == INVALID_SOCKET)
      {
               sprintf(TexteErreur,"Impossible de creer la socket du à l'erreur : %d",WSAGetLastError());
               MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
               return -1; // On termine la fonction et renvoi -1 pour prevenir l'appli principale
      }
 
      /* Config Infos Serveur */  
      ConfigServeur.sin_family = AF_INET;
      ConfigServeur.sin_addr.s_addr = inet_addr(SocketTransmission->IPUtilisee); 
      sscanf(SocketTransmission->PortUtilise, "%d", &PortEcoute); // On reconverti notre port en char vers int
 
      #ifdef _UTILISATIONLOCALE_
      #if TYPEJOUEUR == 1
      ConfigServeur.sin_port = htons(2223);
      #else
      ConfigServeur.sin_port = htons(2222);
      #endif
 
      #else
      ConfigServeur.sin_port = htons(PortEcoute);
      #endif
 
      /* ******************* */
 
      CodeErreur = connect(SocketTransmission->IDSocketServeur, (struct sockaddr*)&ConfigServeur, sizeof(ConfigServeur));
      if (CodeErreur != 0)
      {
            sprintf(TexteErreur,"Impossible de se connecter au serveur du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            closesocket(SocketTransmission->IDSocketServeur);
            return -1;
      }
 
      while(ActiverBoucle) // tant que telle varaible shtdown vaut 1
      {
            if((SocketTransmission->PositionJoueur.x != PositionJLocalPrecedente.x) || (SocketTransmission->PositionJoueur.y != PositionJLocalPrecedente.y))
            {
                 LongueurMessage = send(SocketTransmission->IDSocketServeur, (char*)SocketTransmission, sizeof(StructSocket),0);
                 if (LongueurMessage == SOCKET_ERROR)
                 {
                     sprintf(TexteErreur,"Impossible d'envoyer les données du à l'erreur : %d",WSAGetLastError());
                     MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
                     return -1;
                 }
 
                 PositionJLocalPrecedente.x = SocketTransmission->PositionJoueur.x;
                 PositionJLocalPrecedente.y = SocketTransmission->PositionJoueur.y;
            }
 
            if(!SocketTransmission->ActiverTransmission) // Si l'application demande a terminer le socket
            {
                 ActiverBoucle = shutdown(SocketTransmission->IDSocketServeur, 2); // On envoi un shutdown qui ferme le client et le serveur et qui retourne 0
            }
 
            SDL_Delay(30); // On fait un delay de 30ms pour diminuer l'utilisation du pross
      }
 
      CodeErreur = closesocket(SocketTransmission->IDSocketServeur); // On ferme la socket qui a été ouverte
      if (CodeErreur != 0)
      {
            sprintf(TexteErreur,"Impossible de libérer la socket serveur du à l'erreur : %d",WSAGetLastError());
            MessageBox(NULL,TexteErreur,"Erreur Générale !",MB_OK | MB_ICONERROR);
            return -1;
      }
 
      return 0;
}
Merci d'avance a ceux qui pourront m'aider!!