IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Socket - Problème de communication client/serveur


Sujet :

Réseau C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 6
    Points
    6
    Par défaut Socket - Problème de communication client/serveur
    Bonjour à tous !

    C'est la première fois que je poste sur le forum consacré au C, mais il faut bien commencer un jour...

    Bref, désolé de vous embêtez mais j'ai un petit soucis avec les sockets... Je code en C depuis très peu de temps, et me suis inspiré de différents tutoriels pour arriver au résultat suivant qui n'est pas brillant... Je n'ai, de plus, pas trouvé de solution à ce problème sur les topics existants (mais j'ai peut-être mal cherché !).

    Mon souci avec ce code, c'est que j'aurais aimé réussir à faire communiquer un client et un serveur, chose qui fonctionne partiellement : vous constaterez si jamais vous jetez un oeil aux source que j'utilise pour récupérer les communications dans mon client et dans mon serveur un while. Le problème : à la deuxième éxécution de la boucle sur mon client la communication s'arrête entre les deux... Et il n'ya pas d'erreur concrète qui s'affiche ni sur l'un ni sur l'autre (le dernier envoi du serveur semble bon... Ca serait la récéption du client qui serait donc en cause ?).

    Voila le code du client :

    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
    //headers
    #include <stdio.h>
    #include <winsock2.h>
     
    //libraries
    #pragma comment(lib, "libws2_32.a")
     
    int main()
    {
          //on initialise le fucking winsock >_<
          WSADATA WSAData;
          WSAStartup(MAKEWORD(2,0), &WSAData);
     
          //init socket de connexion
          SOCKET s_con;
          SOCKADDR_IN s_con_param;
          s_con = socket(AF_INET, SOCK_STREAM, 0);
     
          //init des variables du socket de connexion
          s_con_param.sin_addr.s_addr = inet_addr("127.0.0.1");
          s_con_param.sin_family = AF_INET;
          s_con_param.sin_port = htons(58);
     
          //on initialise le buffer qui va récupérer les chaines renvoyés par le serv, et le client
          char buffer_serv[400];
          char buffer_client[400];
          char tempo [400];
     
          //on initialise une variable "erreur" qui quand elle devient vrai termine la connexion avec le serveur
          int error = 0;
     
           //on initialise les variables d'envoi et de réception
          int data_in;
          int data_out;
     
         connect(s_con, (SOCKADDR *)&s_con_param, sizeof(s_con_param));
         int i = 0;
         while (error != 1 && i<=3)
         {
               if (i == 0)
               {
                     data_out = send(s_con, ">>first_connection", 18, 0);
               }
               else
               {
                     data_out = send(s_con, "toto", 4, 0);
                     if (data_out != SOCKET_ERROR)
                     {
                           printf("Envoi OK\n");
                     }
                     else
                     {
                           printf("Erreur lors de l'envoi\n");
                     }
               }
               data_in = recv(s_con, buffer_serv, sizeof(buffer_serv), 0);
               if (data_in != SOCKET_ERROR)
               {
                    printf("%s",buffer_serv);
               }
               else
               {
                   printf("Erreur de reception des donnees\n");
                   error = 1;
               }
               i++;
         }
         closesocket(s_con);
         WSACleanup();
         getchar();
         exit(1);
    }
    Et celui du 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
     
    //headers
    #include <stdio.h>
    #include <winsock2.h>
     
    //libraries
    #pragma comment(lib, "libws2_32.a")
     
    int main()
    {
          //on initialise le fucking winsock >_<
          WSADATA WSAData;
          WSAStartup(MAKEWORD(2,0), &WSAData);
     
          //init socket d'écoute
          SOCKET s_listen;
          SOCKADDR_IN s_listen_param;
          s_listen = socket(AF_INET, SOCK_STREAM, 0);
     
          //init des variables du socket d'écoute
          s_listen_param.sin_addr.s_addr = INADDR_ANY; //a voir
          s_listen_param.sin_family = AF_INET; //idem
          s_listen_param.sin_port = htons(58);
     
          //on bind la total
          bind(s_listen, (SOCKADDR *)&s_listen_param, sizeof(s_listen_param));
     
          //on initialise le socket "client"
          SOCKET s_client;
          SOCKADDR_IN s_client_param;
     
          //on initialise une variable "erreur" qui quand elle devient vrai termine la connexion avec le serveur
          int error = 0;
     
          //on initialise un buffer pour le client et le serveur afind e transmettre des communications
          char buffer_serv[400];
          char buffer_client[400];
     
          //on initialise les variables d'envoi et de réception, de découpage de chaines
          int data_in;
          int data_out;
          int first_time;
          int shut;
     
          if (listen(s_listen, 0) != SOCKET_ERROR)
          {
                printf("Server enabled !\n\nLooking for connections...\n");
                while (error != 1)
                {
                      int length = sizeof(s_client_param);
                      if ((s_client = accept(s_listen, (SOCKADDR *)&s_client_param, &length)) != INVALID_SOCKET)
                      {
                            data_in = recv(s_client,buffer_client,sizeof(buffer_client),0);
                            if (data_in != SOCKET_ERROR)
                            {
                                  first_time = strcmp(buffer_client,">>first_connection");
                                  shut = strcmp(buffer_client,">>shutdown");
                                  if(first_time == 0)
                                  {
                                       data_out = send(s_client,"Welcome on Serv\n\n",22,0);
                                  }
                                  if (shut == 0)
                                  {
                                        error = 1;
                                  }
                                  else
                                  {
                                        printf("%s\n",buffer_client);
                                        data_out = send(s_client,"\nBien recu\n",12,0);
                                        if (data_out != SOCKET_ERROR)
                                        {
                                              printf("Envoi OK\n");
                                        }
                                        else
                                        {
                                              printf("Erreur lors de l'envoi\n");
                                        }
                                  }
                            }
                            else
                            {
                                printf("Erreur de reception des donnees\n");
                                error = 1;
                            }
                      }
                      else
                      {
                            printf("Ecoute refusee\n");
                            error = 1;
                      }
                }
                closesocket(s_client);
                closesocket(s_listen);
                WSACleanup();
                exit(1);
          }
          else
          {
                printf("Failure...\n");
                WSACleanup();
                exit(1);
          }
    }
    Je me triture l'esprit depuis hier soir pour trouver une solution, mais je ne vois pas, c'est pourquoi je suis là

    Voila, si jamais quelqu'un a 10 minutes à perdre !!

    Merci d'avance

    PS : je développe sous windows avec devc++ et le compilateur gcc. Ci-joint une capture du résultat obtenu.
    Images attachées Images attachées  

  2. #2
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    s_client = accept(s_listen, (SOCKADDR *)&s_client_param, &length)) != INVALID_SOCKET
    Tu fais un accept à chaque tour, c'est normal que ça bloque. accept est bloquant

    Pour le faire proprement, il te faudrait utiliser des fd_set et des select.

    Une solution temporaire (juste si tu veux voir un peu comment ça marche) serait de sortir accept de la boucle. Evidemment, tu ne pourrais avoir qu'un seul client.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                                        data_out = send(s_client,"\nBien recu\n",12,0);
                                        if (data_out != SOCKET_ERROR)
    Tu fais une erreur. send, write, recv, read retourne le nombre d'octet effectivement lu ou envoyé et n'a donc pas de rapport avec SOCKET_ERROR.
    Il faut normalement au moins tester si c'est égale à -1 (dans ce cas il y a eu une erreur).

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Coucou,

    Merci beaucoup, je viens de tester, et effectivement en mettant le accept au dessus du while et ça fonctionne impecable !

    En revanche pour ce qui est de SOCKET_ERROR, ne s'agit-il pas d'une variable spéciale (qui contiendrait justement un entier ?) ? Il est vrai que je n'ai trouvé celle-ci utilisée que dans un seul code (mais bon j'en ai regardé deux en même temps ). Dans le tutorial disponible sur developpez (de TheWalrus sur http://c.developpez.com/WalrusSock/ ) celui-ci utilise la variable INVALID_SOCKETqui me semblait redondante SOCKET_ERROR (qui me parait marcher, étant donné que quand je clos le serveur le client me renvoit bien une erreur).

    Sinon, pour améliorer un peu tout ça, je vais faire des recherches sur fd_set et select ! Merci encore

  4. #4
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Alors, dans Winsock2.h, on trouve :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef u_int	SOCKET;
     
    #define SOCKET_ERROR	(-1)
     
    int PASCAL send(SOCKET,const char*,int,int);
    Ici, l'implémentation de SOCKET est un entier, mais il pourrait y avoir des implémentations différentes. send retourne un entier (ssize_t sous Unix me semble-t-il) qui indique le nombre d'octet effectivement envoyé et n'a donc aucun rapport avec SOCKET (même si dans ce cas ci, c'est effectivement implémenté par un entier, mais ça aurait pu être autre chose) :

    SOCKET_ERROR va être utilisé pour vérifier qu'une fonction du genre : socket retourne vraiment un socket valide. En effet, la fonction socket pourrait ne pas réussir à créer le socket et retourner SOCKET_ERROR.

    Sous linux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     ssize_t
         send(int s, const void *msgbuf, size_t len, int flags);

    J'ai jetté un rapide coup d'oeil au cours, et je pense qu'il est beaucoup trop laxiste sur les erreurs. En réseau, les erreurs sont très vite arrivé, il est absolument nécessaire de tester les valeurs de retours.
    Typiquement, il fait juste : bind(sock, (SOCKADDR *)&sin, sizeof(sin));, la probabilité que bind rate est importante, notamment si tu lances deux fois l'applications de suite avec le même port d'écoute.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7
    Points : 6
    Points
    6
    Par défaut
    Très bien, je prends note (et je change mon code avec un test sur <0 à la place de SOCKET_ERROR qui est donc effectivement inadapté !)
    Merci pour ces précisions

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de communication client-serveur!
    Par nixmind dans le forum Windows XP
    Réponses: 1
    Dernier message: 29/08/2009, 13h29
  2. Problème de communication client-serveur!
    Par nixmind dans le forum Services
    Réponses: 1
    Dernier message: 29/08/2009, 13h16
  3. Réponses: 8
    Dernier message: 18/04/2007, 14h26
  4. [ServerSocket]Problème communication client-serveur udp sur linux
    Par gdecrouez dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 29/09/2006, 14h59
  5. Problème de communication client/serveur
    Par alex6891 dans le forum Développement
    Réponses: 10
    Dernier message: 09/03/2006, 13h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo