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 :

les sockets en C sous linux


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut les sockets en C sous linux
    Bonjour à tous,

    voila j'essaye de faire communiquer mon PC avec ma carte raspberry via les sockets et je coince un peu, à vrai dire je n'arrive pas a connecter mon pc avec la raspberry.

    Le programme sur mon PC (windows) est fait via Qt, qui a une méthode toute faite pour me connecter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    connectToHost(host, port);
    j'ai donc placé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Socket -> connectToHost(10.0.0.1,  15020);
    et le tour est joué.

    mais sur ma carte raspberry je dois tout configurer. Je dois donc définir sur ma raspberry un port sur laquel mon programme sera exécuté. J'ai donc fait :
    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
     
    int server, client;
    struct sockaddr_in server_addr;
    socklen_t size:
     
    client = socket(AF_INET, SOCK_DGRAM, 0); // la connexion se fait en UDP
    if(client < 0){
         printf("error socket created");
         exit(1);
    }
    printf("socket succed");
     
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(15020);
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
     
    if(blind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
         printf("error bind");
         exit(1);
    }
    printf("bind OK");
    size = sizeof(server_addr)
    listen(fd, 1);
    server = accept(fd, (struct sockaddr*)&server_addr, &size);
    if(server < 0){
         printf("error accept");
         while(server < 0){
              server = accept(fd, (struct sockaddr*)&server_addr, &size);// j'attend que le client se connecte à mon port
         }
    }
     
    while(server > 0){
         printf("connected with client");
         while(1);
    }
    le probleme est que je n'arrive pas à me connecter à mon client, avez vous une idée du probleme ?
    merci d'avance

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Il n'y a pas de serveur auquel se connecter puisque ton programme serveur ne compile pas. Tu bloques où exactement ?

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Si tu fais de l'UDP, il n'y a pas d'accept() à faire. Voir http://broux.developpez.com/articles/c/sockets/#L3-4-2

    le probleme est que je n'arrive pas à me connecter à mon client
    Au passage, ton PI est serveur si on s'y connecte, pas client.

    Si tu as le choix du langage, ce serait plus facile en Python qu'en C sur Raspberry Pi.

  4. #4
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    merci pour vos réponses, j'ai retiré le listen et accept mais quand je fais netstat -puan mon serveur(10.0.0.1:15020) a son état vide donc ca ne marche pas

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Il n'y a pas de serveur auquel se connecter puisque ton programme serveur ne compile pas. Tu bloques où exactement ?
    mon programme se compile mais l 'état ne met pas etasblished donc j'en déduis que ca ne marche pas

  6. #6
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par cosmoff Voir le message
    mon programme se compile mais l 'état ne met pas etasblished donc j'en déduis que ca ne marche pas
    if(blind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){ <- je ne connais pas la fonction blind, j'en déduis que :
    • soit ton programme ne compile pas ;
    • soit ce code n'est pas pertinent, puisque différent.


    Dans les deux cas, nous ne disposons pas des informations nécessaires pour appréhender ton problème. Donne-nous le code exact du serveur tel que tu l'as compilé sur le Pi.

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    alors le code exact sur mon serveur PI est :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <netdb.h>
     
     
    int main(void){
     
    int server, client;
    struct sockaddr_in server_addr;
     
     
    client = socket(AF_INET, SOCK_DGRAM, 0); // la connexion se fait en UDP
    if(client < 0){
         printf("error socket created");
         exit(1);
    }
    printf("socket succed");
     
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(15020);
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
     
    if(bind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
         printf("error bind");
         exit(1);
    }
    printf("bind OK");
    while(1); 
     
    }
    mais impossible de connecté mon client à mon serveur avec ce code.

  8. #8
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    C'est à prévoir, while(1); va mouliner en boucle jusqu'à la fin des temps. Tu dois explicitement récupérer le message du client via recvfrom. Des exemples se trouvent ici.

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    C'est à prévoir, while(1); va mouliner en boucle jusqu'à la fin des temps. Tu dois explicitement récupérer le message du client via recvfrom. Des exemples se trouvent ici.
    En faite je voulais d'abord voir si ma connexion fonctionnait avant d'émettre un message, ce n'est pas possible?

  10. #10
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Ce serait possible en TCP mais ça ne l'est pas en UDP non : c'est un protocole connectionless (sans connexion). Comme Bktero l'a mentionné on n'invoque pas accept. Tu envoies et reçoit les paquets (datagrammes) tels quels, potentiellement désordonnés : il n'y a pas de notion de flux. Tu peux implémenter une notion de canal connecté au-dessus d'UDP dans la couche application mais c'est à toi de le faire, l'OS s'en lave les mains.

    D'où mes prochaines questions :
    • es-tu sûr de devoir communiquer via UDP ?
    • n'as-tu pas un pendant de la fonction connectToHost côté serveur qui te permette d'effectuer un handshake avec le client une fois le socket ouvert ?

  11. #11
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    @cosmoff : je crois que tu n'as pas pleinement compris la différence entre UDP et TCP. UDP utilise des datagrams, des paquets qu'on balance dans la nature sans se soucier de la réception ; TCP utilise des sockets, qui sont un tuyau ouvert avec le client sur lequel on envoie des paquets en s'assurant qu'ils sont bien reçus. Schématiquement, UDP revient à envoyer des SMS, TCP revient à une conversation téléphonique. La seule façon pour s'assurer que tu arrives à contacter un serveur UDP est donc bien de lui envoyer un paquet et qu'il le reçoive ; tu ne peux pas tenter de d'y connecter, par définition.

    @Matt_Houston : connectToHost() est une méthode qui permet justement de faire une sorte de connexion virtuelle au-dessus d'UDP Voici ce que dit la doc de Qt :
    Citation Envoyé par http://doc.qt.io/qt-4.8/qabstractsocket.html#details
    QAbstractSocket's API unifies most of the differences between the two protocols. For example, although UDP is connectionless, connectToHost() establishes a virtual connection for UDP sockets, enabling you to use QAbstractSocket in more or less the same way regardless of the underlying protocol.

  12. #12
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Ouaip mais du coup l'OP a-t-il accès aux specs de ce protocole ? Parce qu'autrement il va falloir lier le programme serveur avec le module Qt correspondant, soit en en faisant un projet C++ () soit en le wrappant dans une bibliothèque C++ à part..

  13. #13
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Je ne pense pas que cela soit un problème. L'application client sur PC et codée en Qt ouvre une socket puis envoie et reçoit des données via celle-ci. S'il s'avère que la socket est une vraie socket TCP, il y a aura des erreurs en cas d'échec de communication avec la paire distante (impossible d'établir la connexion, coupure de la connexion ouverte, etc). Si cette socket est en fait un wrapper au-dessus d'UDP, je pense ce que les erreurs de ce genre disparaitront, comme si la connexion était toujours OK. Enfin... c'est ce que je suppose en lisant la documentation. cosmoff ne nous a pas dit si l'application Qt lui renvoyait des erreurs.

  14. #14
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    merci pour vos réponses,

    Alors Qt peut me renvoyer des erreurs. Par exemple quand je lance la méthode connectToHost(host, port) je peux recevoir une erreur avec la méthode waitForConnected(5000) qui est = 0 quand je ne peux pas me connecter au serveur.

    Alors oui, j'ai choisie le protocole UDP car mon projet et d'envoyer plusieurs dizaines de fois une commande par seconde, donc pas besoin que le paquet émis soit bien recu et/ou correctement transmis.

    j'ai essayé d'envoyer un message sans passer par Qt, j'ai fait sur ma raspberry un server.c et sur mon linux un client.c et il est impossible de transmettre un message.... pourtant je l'envoie plusieurs fois.

    Etes vous sur que mon code server.c est bon?

  15. #15
    Membre du Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2013
    Messages : 274
    Points : 56
    Points
    56
    Par défaut
    le code fonctionne entre linux et ma raspberry, le probleme vient de Qt donc je vais me pencher sur ce probleme

Discussions similaires

  1. Quels sont les outils de développement sous Linux ?
    Par Community Management dans le forum Linux
    Réponses: 120
    Dernier message: 11/10/2015, 11h17
  2. Réponses: 4
    Dernier message: 28/02/2008, 18h40
  3. Réponses: 5
    Dernier message: 05/01/2007, 21h26
  4. Les entêtes d'identification sous Linux
    Par Madmac dans le forum Linux
    Réponses: 6
    Dernier message: 19/11/2006, 08h17
  5. Mettre à jours les dev d'OpenGL sous Linux
    Par Yno dans le forum OpenGL
    Réponses: 6
    Dernier message: 06/11/2006, 09h17

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