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

C++ Discussion :

Problème de Sockets


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut Problème de Sockets
    Salut !

    Je fais actuellement un simple petit client serveur car je n'ai besoin d'envoyer que de petites informations d'un programme à l'autre et ce serait trop lourd d'utiliser un ORB pour faire cela.

    J'ai donc décidé d'utiliser des sockets, et j'ai un tout peit problème que je ne comprend vraiment pas ... je lance mon serveur, et il attend la connexion ... je lance mon client et il me dit qu'il est connecté, mais mon serveur reste en attente de connexion et ne bouge pas de là ...

    Voici mon code, est-ce que quelqu'un aurait une idée ?

    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
    #include <winsock2.h>
    #include <iostream>
     
    int main(int argc, char* argv[]){
     
      int attenteSocket;
      int acceptation;
      int sock;
      int bindS;
      int nb;
      char* clavier;
      int port;
      int lire;
      int i;
     
      char tampon[512];
     
      SOCKADDR_IN emetteur;
      SOCKADDR_IN hote;
      struct hostent* host;
     
      int longAddr;
     
      // Vérification du nombre de paramètres
      if(argc == 3){
        if (!strcmp(argv[1],"-port")) port = (int)argv[2];
    	else port = 9999;
      } else {
        port = 9999;
      }
     
      WSADATA WSAData;
      WSAStartup(MAKEWORD(2,0), &WSAData);
     
      // Résolution DNS à partir du nom de la machine
      host = gethostbyname("localhost");
     
      //Initialisation de la structure sockaddr_in
      hote.sin_family = AF_INET;
      hote.sin_port = htons(port);
     
      memcpy(&hote.sin_addr,
    	 host->h_addr,
    	 host->h_length);
     
      for(int i=0; i<8; i++){
        hote.sin_zero[i] = 0;
      }  
     
      // Création du socket
      sock = socket(AF_INET, SOCK_STREAM, 0);
     
      // Test de la validité de la création du socket
      if(sock == -1){
        printf("Erreur à l'ouverture du socket\n");
        exit(-1);
      } 
     
      bindS = bind(sock, (SOCKADDR*)&hote, sizeof(hote));
     
      // Test de la validité du bind
      if(bindS == -1){
        printf("Erreur lors du bind du socket\n");
        exit(-1);
      } 
     
      printf("Socket créé et bindé\n");
     
      listen(sock,0);
      do{
        attenteSocket = listen(sock, 0);
      } while(attenteSocket == -1);
     
      printf("En attente de connexion\n");
     
      do{
        acceptation = accept(sock, (SOCKADDR*)&emetteur, &longAddr);
      } while(acceptation == -1);
     
      // Attente tant qu'on n'appuie pas sur la touche Espace
      printf("Appuyer sur espace pour lancer la consommation\n");
      do{
        scanf("%c",clavier);
      }while(!strcmp(clavier, " "));
     
      printf("Consomation lancée\n");
     
      while(1){
        lire = recv(acceptation, tampon, sizeof(tampon), 1024);
        if(lire != -1){
          printf("%s\n",i++,tampon);
        }
      }
     
    }
    Code 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
    bool Acquisition::initConnexion(int argc , char* argv[]){
     
    	bool res = true;
    	WSADATA WSAData;
    	WSAStartup(MAKEWORD(2,0), &WSAData);
     
    	if(argc == 5){
    		if(!strcmp(argv[1],"-host") && !strcmp(argv[3],"-port")){
    			nomDest = argv[2];
    			port = (int)argv[4];
    		} else if(!strcmp(argv[3],"-host") && !strcmp(argv[1],"-port")){
    			nomDest = argv[4];
    			port = (int)argv[2];
    		}
    	} else if(argc == 3) {
    		if(!strcmp(argv[1],"-host")){
    			nomDest = argv[2];
    			port = 9999;
    		} else if(!strcmp(argv[1],"-port")){
    			nomDest = "localhost";
    			port = (int)argv[2];
    		}
        } else if(argc == 1) {
    		nomDest = "localhost";
    		port = 9999;
    	} else {
    		usage(argv[0]);
    		res = false;
    	}
        int b = -10;
    	if (res){
    		// Résolution DNS à partir du nom de la machine
    		host = gethostbyname(nomDest);
    		//Initialisation de la structure sockaddr_in
    		destinataire.sin_family = AF_INET;
    		destinataire.sin_port = htons(port);
    		memcpy(&destinataire.sin_addr, host->h_addr, host->h_length);
    		for(int i=0; i<8; i++) destinataire.sin_zero[i] = 0;
     
    		// Initialisation du socket
    		sock = socket(AF_INET, SOCK_STREAM, 0);
    		if(sock == -1){
    			std::cerr << "Erreur à l'ouverture du socket\n" << std::endl;
    			res = false;
    		} else { 
     			//b= bind(sock, (SOCKADDR *)&destinataire, sizeof(destinataire));
    		}
     
    		connecte = connect(sock, (SOCKADDR*)&destinataire, sizeof(destinataire));
    		if(connecte == -1){	
    			std::cerr << "Echec de la connexion à " << nomDest << std::endl;
    			res = false;
    		} else {
    			std::cout << "Connecté" << std::endl;
    		}
    	}
     
    	return res;
    }
    Pour le client la connexion se fait dans une fonction d'initialisation, et l'on n'envoie ni ne reçoit rien pour le moment ...

    Le serveur reste bloqué en attente de connexin alors que le client affiche connecté ...

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    listen() met seulement le socket dans un état d'écoute.
    La fonction d'attente, c'est accept().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut
    Oui je sais ...

    En fait il affiche bien le message "en attente de connexion" (oui je sais je mélange le C et le C++ mais je le fais à la va vite ce serveur c'est juste un petit truc pour tester mon client)

    Et après il ne valide jamais le accept ... ... que le client se considère bien comme connecté ...

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Ah, je n'avais pas vu le accept après ta boucle de listen() qui me tirait l'oeil.

    D'ailleurs, renonces-y (aux deux boucles) : Car c'est le genre d'opération "qui a foiré, foirera" qui fera plonger ton programme dans une boucle infinie...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut
    Ok ...

    Mais ça ne marche toujours pas ... il attend toujours une connexino alors que le client se considère comme connecté ...

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Au fait : puisque tu es en winsock, utilise winsock jusqu'au bout: Tes sockets doivent être des SOCKET (un type non-signé) et non des int, et tu dois comparer à INVALID_SOCKET et non -1 (pour le retour de accept()).

    Si ça trouve, tu as une erreur de signe, mais je n'y crois pas trop.

    PS: Je crois que j'ai trouvé! longAddr n'est pas initialisé, alors que c'est une valeur in/out et non pas out...

    PPS: C'est normal que le client se croie connecté. Le nombre maximum de clients qui se croient connectés est déterminé par le second paramètre de listen(), mais je crois que c'est toujours au moins 1 même si tu mets zéro...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    un listen(sock,1);
    suffit, pas besoin de sortir une boucle avec des tests.
    Ah oui le second paramètre ne doit jamais être nul ou négatif, mais toujours positif. Sinon ca n'a aucun sens. Par conséquent met 1 ou plus, on conseil générallement jusque 5, plus serait superflux. Dans ton cas, 1 me semble parfait.

    Ensuite je suis d'accord travail, avec de l'arithmetique non signée, c'est souvent source de moins de probleme que l'arithmetique signée, et puis les constantes systemes sont là pour ca. Ca évite aussi les problemes, et générallement, sous linux par exemple, une acceptation avec une socket nulle renverra 0. Ca aussi c'est un cas d'erreur donc ...

    En ce qui concerne l'acceptation... Je te suggere de casser ta boucle, ou du moins de rajouter une ligne supplémentaire pour indiquer à l'écran toute tentative de connexion infructueuse, donc tout résultat à -1. Cela serait suceptible d'être très intéressant et très instructif, car à priori je ne vois aucun probleme du coté du serveur.

    Essaie donc d'ajouté la ligne :
    if (acceptation == -1) printf("Echec d'acceptation. \n");
    dans la boucle do {...} while (acceptation != -1)

    En effet rassure toi, la fonction accept telle que tu l'a configurée est blocante, par conséquent, elle ne retourne un résultat qu'a l'occasion d'un évenement réseau sur la socket d'écoute.

    je dirais même que dans ce cas la boucle est superflux.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut
    Merci c'était bien le champ longAddr qui n'était pas initialisé et qui bloquait l'accept() ...

    Bon maintenant je vais essayer de déloquer les autres pb ... lol ... et je reviendrais demander conseille si je n'y arrive pas, mais là ça devrait aller...

    Encore merci

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut
    Euh en fait deux petites questions supplémentaries ...

    1 ) Est-ce que la constante INVALID_SOCKET est à utiliser aussi pour vérifier si le bind, la lecture, ... sont bons ou alors il y a d'autres constantes système ?

    2 ) Un socket est-il bidirectionnel ? (en gros le serveur et le client peuvent s'envoyer mutuellement des infos par le même socket ou non ?)

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    1. Sous Windows, on a tendance à utiliser SOCKET_ERROR au lieu de -1 pour pratiquement toutes les fonctions socket qui retournent autre chose qu'un socket: listen(), bind(), send(), recv(), etc, WSAStartup() étant l'exception la plus notable, puisqu'elle retourne directement le code d'erreur au lieu de -1.
      Tout cela est généralement décrit dans l'aide de chaque fonction sur la MSDN.
    2. Oui.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut
    Les sockets sont donc bi-directionnels ...

    Tant mieux, mais mon serveur ne veut pas envoyer de données ... après avoir réalisé la connexion, j'essaye de faire dans le serveur (pour envoyer au client) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int n = send(sock, "coucou\r\n", 7, 0);
    , et il me met n à SOCKET_ERROR ... donc il n'a pas envoyé ...

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Il faut utiliser le socket retourné par accept() et non pas le socket d'écoute.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Par défaut
    Ok merci...

    Bon ça a l'air de marcher, je vais faire le gros test maintenant ...

    Encore meric pour tout

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

Discussions similaires

  1. Problème de sockets
    Par the_penguin dans le forum Réseau
    Réponses: 8
    Dernier message: 13/04/2006, 19h19
  2. Problême de Socket avec un applet java (RMI/policy)
    Par Vesperal dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 12/04/2006, 12h00
  3. Réponses: 2
    Dernier message: 26/03/2004, 09h15
  4. [Kylix] Problème de socket
    Par RaygKross dans le forum EDI
    Réponses: 1
    Dernier message: 01/03/2004, 19h41
  5. Mysql ne se lance pas problème de socket
    Par Riko dans le forum Installation
    Réponses: 5
    Dernier message: 05/02/2004, 09h28

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