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 :

[Socket] Communication Java <--> C++


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut [Socket] Communication Java <--> C++
    Bonjour,

    Je souhaite faire communiquer deux programmes avec des sockets, l'un en Java, l'autre en C++.

    Mon programme Java fait office de serveur et celui en C++ de client.
    Côté Java je n'ai pas de soucis (j'ai déjà testé de faire ma communication avec deux programmes Java et ça marche nickel)

    Par contre je n'obtiens pas du tout ce que je veux avec un client c++ (je dois forcément foirer un truc un moment), sur ma console, j'ai un caractère bizarre qui s'affiche (la fraction 1/4 suivi d'un Y majuscule avec un accent) et ce, peu importe ce que j'envoie (un int, un string, ...)
    Ci-dessous mon code C++, je peux vous donner le code Java si vous le souhaitez

    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 <iostream>
    #include <winsock2.h>
    #include <stdio.h>
    #pragma comment(lib, "ws2_32.lib")
     
    using namespace std;
     
    int main()
    {
        WSADATA WSAData;
        WSAStartup(MAKEWORD(2,0), &WSAData);
        SOCKET sock;
        SOCKADDR_IN sin;
        char buffer[32];
     
        sin.sin_addr.s_addr	= inet_addr("127.0.0.1");
        sin.sin_family		= AF_INET;
        sin.sin_port		= htons(13370);
        sock = socket(AF_INET,SOCK_STREAM,0);
     
        if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
        {
            cout<<"connexion"<<endl;
            if(recv(sock, buffer, 32, 0) != SOCKET_ERROR)
            {
                cout<<"reception : "<<buffer<<endl;
                printf("%s", buffer);
            }
            else
                cout<<"fail reception";
        }
        else
            cout << "fail connexion";
        closesocket(sock);
        WSACleanup();
        return 0;
    }
    Merci d'avance

    pikmin

  2. #2
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Utilise tu les même propriétés de socket entre le client et le serveur?

    Qu'essaie-tu d'envoyer avec ton programme java?
    que dois contenir le message? Il faut savoir ce que tu envois et dans quel format pour ensuite savoir comment tu dois le lire.

    Si tu as des erreurs coté C++ tu peux utiliser
    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    pour avoir une raison plus précise.

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par jabbounet Voir le message
    Utilise tu les même propriétés de socket entre le client et le serveur?
    c'est-à-dire exactement ?

    Citation Envoyé par jabbounet Voir le message
    Qu'essaie-tu d'envoyer avec ton programme java?
    que dois contenir le message? Il faut savoir ce que tu envois et dans quel format pour ensuite savoir comment tu dois le lire.
    un entier ou une chaine de caractères
    j'utilise un DataOutputStream pour l'envoi avec la fonction writeInt pour les int, et j'ai essayé writeChars, writeBytes et writeUTF pour une chaine de caractères.

    Citation Envoyé par jabbounet Voir le message
    Si tu as des erreurs coté C++ tu peux utiliser
    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    pour avoir une raison plus précise.
    c'est bien ça le problème, je n'ai pas d'erreur la condition de la fonction recv est respectée.

    Pour info, voici mon code Java :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    ServerSocket service= new ServerSocket(13770); 
    Socket connexion = service.accept(); 
    boolean continu=true;
    DataOutputStream dos = new DataOutputStream(connexion.getOutputStream());
    while(continu)
    {
                dos.writeInt(5);
                dos.write
                dos.flush();
                dos.close();
    }
    connexion.close();

  4. #4
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    j'viens de voir que si je rajoute cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bind(sock, (SOCKADDR *)&sin, sizeof(sin));
    mon programme est en attente de réception d'information (il passe à la ligne 24 en affichant "connexion" et après plus rien)

    mais bon ça m'avance pas trop vu que la connexion semble bel et bien être réalisée

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Il me semble que le data outputstream sérialise les données dans un format interne à Java, qui est fait pour être désérialisé par un DataInputStream...donc ton client c++ en perd son latin parce que la STL n'a jamais entendu parler de ce protocole...il faudrait plutôt que tu utilise un protocole standard et identique des deux côtés plutôt que les streams de sérialisation faits pour communiquer de java à java...

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 630
    Points : 30 699
    Points
    30 699
    Par défaut
    Salut,

    *Si mes souvenirs sont bons*, il me semble que les chaines de caractères sont d'offices codées en unicode ou similaires en java...

    Du coup, certains caractères sont en réalité codé sur deux bytes ou plus. Si tu essaye de les récupérer avec un char * ou (ce serait quand meme mieux ) avec une std::string, qui travaille avec des caractères codés sur un byte, tu auras fatalement des problèmes

    Le problème de la gestion unicode a souvent été abordé ici, une petite recherche devrait te permettre de trouver comment te dépêtrer

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,
    *Si mes souvenirs sont bons*, il me semble que les chaines de caractères sont d'offices codées en unicode ou similaires en java...
    Exact, tes souvenirs sont bons. Mais à mon avis (cf post + haut) il y a un gotcha: l'objet que pikmin utilise pour sérialiser est un stream de format binaire qui est uniquement conçu pour la sérialisation/désérialisation interne à Java. Il faudrait qu'il passe à un autre flux pour écrire ses chaines de caractères...et qu'il fasse en sorte que ses valeurs numériques soient passées au format texte, et non binaire qui n'a pas de raison particulière d'être compatible entre DataStream et les flux de la STL (voire, vu qu'ils sont faits pour du format texte, toutes les raisons de NE PAS l'être...).
    Ensuite, en Java il faudrait qu'il fasse en sorte de contrôler son encodage de sortie (l'API le permet) de manière à pouvoir décoder à la sortie...je connais moins les possibilités en c++, mais je suppose qu'il y a moyen de trouver des libs adaptées.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 630
    Points : 30 699
    Points
    30 699
    Par défaut
    Peut etre utiliser les fonction hton* et ntoh* dans ce cas

  9. #9
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Peut-être, java transmettant toujours en big-endian. Mais il faudrait être sûr que le format binaire en question est compris par les opérateurs de flux...ça faudrait tester. Ceci dit si ce n'est pas dans l'API officielle ils se donnent le droit de changer quand ils veulent...
    EDIT: je voudrais être sûr d'être clair: par encodage j'entendais encodage de jeu de caractères: demander explicitement d'émettre en UTF8, par exemple, pour savoir comment décoder côté récepteur...java adopte automatiquement l'encodage par défaut de la plateforme quand on ne précise pas. Ca peut jouer des tours (en particulier si client et serveur ne tournent pas sur la même machine).

  10. #10
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Merci pour vos réponses !

    J'ai testé différents trucs du coup, mais toujours le même résultat

    Citation Envoyé par koala01
    Si tu essaye de les récupérer avec un char *
    Si je mets char *buffer; à la place de char buffer[512]; j'obtiens une erreur, la 10014 de WSAGetLastError()
    The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).
    Du côté Java, j'ai testé l'envoie avec un DataOutputStream, un OutputStream et un PrintWriter. J'ai essayé avec un entier ou un String et avec la fonction getBytes avec et sans le paramètres "UTF-8".

    J'avais vu aussi l'histoire du codage sur un ou deux bytes des caractères et je pense que c'est ça + ce qu'a souligné therwald à propos de la sérialisation de Java qui pose problème. Donc je pense que je vais continuer à chercher dans ce sens là, je vous tiens au courant.
    Bien sûr si vous avez d'autres idées je suis preneur

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 630
    Points : 30 699
    Points
    30 699
    Par défaut
    Citation Envoyé par pikmin Voir le message
    Merci pour vos réponses !

    J'ai testé différents trucs du coup, mais toujours le même résultat
    Si je mets char *buffer; à la place de char buffer[512]; j'obtiens une erreur, la 10014 de WSAGetLastError()
    Oui, c'est normal... char *buf (je l'ai renommé juste pour éviter la confusion) ne fait que déclarer un pointeur sur char nommé buffer alors que char buffer[512] déclare un tableau de 512 caractères nommé buffer.

    si tu es dans le deuxième cas, lorsque tu utilise buffer, tu utilise en réalité un pointeur sur caractère pointant sur l'adresse mémoire du premier caractère de l'array qui en contient 512.

    Par contre, dans le premier cas, il faut, avant d'essayer d'accéder à "ce qui est pointé par le pointeur" (AKA buf) veiller à ce que l'adresse qu'il contient soit bel et bien... l'adresse mémoire à laquelle nous trouverons le premier caractère d'un array de caractères utilisable.

    Le problème, c'est que cela reste toujours des caractères codés sur... un byte, alors que Unicode ( et donc, si ton serveur envoie bien une chaine de caractères, la chaine que tu essaye de récupérer) permet l'utilisation de caractères codés sur deux ou trois bytes.

    Il faut donc soit utiliser un type de caractères codé sur plus de 1 byte (wchar_t, par exemple), soit veiller à convertir la chaine de caractères (pour autant que l'on soit sur que c'est bien ce que le serveur envoie ) unicode en chaine de caractères "ASCII".

    Tu trouveras sans doute quelques pistes à explorer du coté des entrées de la FAQ Comment manipuler des chaînes de caractères Unicode ? et Comment effectuer les conversions de texte ASCII <-> Unicode ?

    Mais, je n'insisterai jamais assez là dessus, il faut impérativement savoir ce qui est renvoyé par le serveur (si tu veux explorer les pistes dont je viens de parler, il faut qu'il renvoye des chaines de caractères ) et, s'il renvoie des chaines de caractères, savoir quel jeu de caractères il utilise (cf la remarque de therwald)
    Du côté Java, j'ai testé l'envoie avec un DataOutputStream, un OutputStream et un PrintWriter. J'ai essayé avec un entier ou un String et avec la fonction getBytes avec et sans le paramètres "UTF-8".

    J'avais vu aussi l'histoire du codage sur un ou deux bytes des caractères et je pense que c'est ça + ce qu'a souligné therwald à propos de la sérialisation de Java qui pose problème. Donc je pense que je vais continuer à chercher dans ce sens là, je vous tiens au courant.
    Bien sûr si vous avez d'autres idées je suis preneur
    C'est parce qu'il faut travailler sur les deux tableaux :
    D'un coté s'assurer du format réellement renvoyé par le serveur (chaine de caractères UTF8, ou ISO8859-1 "latin 1" par exemple)
    D'un autre, s'assurer de récupérer les données dans le bon jeu de caractères et / ou de le convertir en caractère ASCII

  12. #12
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    ok, ok, merci beaucoup, je testerai tout ça demain je pense.

    Merci beaucoup pour les précisions

  13. #13
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Bon j'ai encore essayé différents trucs aujourd'hui. J'ai d'abord ajouté les fonctions widen et narrow de la FAQ pour la conversion unicode <--> ASCII.
    J'ai aussi trouvé ça qui pourrait être intéressant : http://msdn.microsoft.com/en-us/libr...8vs.71%29.aspx

    Du coup je me suis attelé à de petits tests avec ces fonctions, mais à chaque fois que je veux utiliser narrow ou widen, mon programme plante avec le message suivant :
    This application has requested the Runtime to terminate it in an unusual way.
    Bref, j'ai pas trop avancé, mais bon pas trop le choix, donc j'vais continuer à chercher. J'vais voir si avec Java y'a pas moyen d'envoyer des données selon un format plus simple

  14. #14
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    This application has requested the Runtime to terminate it in an unusual way.
    Il me semble que l'ami W$ te signale par là qu'il y a eu une uncaught exception...

    Concernant Java, envoie donc tes variables à base de Double.toString() et consorts...et pour contrôler comment c'est encodé, tu écris tes string en injectant getBytes(String encoding) dans le flux de la socket.

  15. #15
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Bon j'crois que je vais abandonner, je commencer à en avoir sérieusement marre là. J'ai encore fait des tests, rien ne marche, j'ai essayé de réutiliser du code trouvé sur le net, pareil.

    Du coup j'vais essayer de trouver une autre manière de faire.

    Merci encore de votre aide

  16. #16
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Bonjour,

    Après avoir demandé de l'aide à des potes, j'ai finalement trouvé la réponse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ServerSocket service= new ServerSocket(1337);
    Socket connexion = service.accept();
    PrintWriter pw = new PrintWriter(connexion.getOutputStream());
    pw.print("toto");
    pw.flush();
    pw.close();
    connexion.close(); 
    service.close();
    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
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    SOCKET sock;
    SOCKADDR_IN sin;
    char buffer[512];
    sin.sin_addr.s_addr	= inet_addr("127.0.0.1");
    sin.sin_family		= AF_INET;
    sin.sin_port		= htons(13370);
    sock = socket(AF_INET,SOCK_STREAM,0);    
    if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
    {
            cout<<"connexion"<<endl;
            const int result = recv(sock, buffer, sizeof(buffer), 0);
            if(result != SOCKET_ERROR)
            {
                    string s(buffer,result);
                    cout << "message : '" << s << "'" << endl;
            }
            else
                    cout<<"fail reception";
    }
    closesocket(sock);
    WSACleanup();

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    On en vient à la question du type de stream: utiliser des stream texte au lieu de streams binaires...
    Dans ton application concrète, toutefois, attention à bien contrôler l'encodage, surtout si client et serveur tournent sur des machines différentes...
    En tous cas, c'est cool que tu aies une solution.

  18. #18
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 39
    Points : 19
    Points
    19
    Par défaut
    Je l'avais déjà essayé ce stream (pas en premier certes), mais y'avait aussi la manière de récupérer le message côté client.

    Pour ce qui est de l'encodage, je ferais des tests sur machines différentes d'ici la rentrée.

    Par contre j'ai voulu éditer mon premier post pour mettre "Résolu" mais j'ai pas trouvé le bouton correspondant

  19. #19
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par pikmin Voir le message
    Par contre j'ai voulu éditer mon premier post pour mettre "Résolu" mais j'ai pas trouvé le bouton correspondant
    Pas même dans Outils de la discussion? (simple suggestion, je n'ai jamais eu à le faire jusqu'ici...)

  20. #20
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2011
    Messages
    1 255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 255
    Points : 2 627
    Points
    2 627
    Par défaut
    Citation Envoyé par pikmin Voir le message
    Par contre j'ai voulu éditer mon premier post pour mettre "Résolu" mais j'ai pas trouvé le bouton correspondant
    Regarde la signature de koala01 il l'explique bien. (pas besoin d'éditer un de tes messages)

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

Discussions similaires

  1. Communication Java - Silverlight via Socket
    Par Seb59118 dans le forum Silverlight
    Réponses: 4
    Dernier message: 02/12/2009, 18h53
  2. La communication par socket en Java
    Par akreem dans le forum NetBeans
    Réponses: 1
    Dernier message: 27/10/2009, 11h41
  3. [socket] Communication bloquante
    Par Tex-Twil dans le forum Développement
    Réponses: 3
    Dernier message: 29/03/2006, 17h33
  4. Communication JAVA & PL/SQL
    Par Titouf dans le forum PL/SQL
    Réponses: 1
    Dernier message: 12/01/2006, 11h18
  5. [Socket] Communication à l'aide de sockets (théorie)
    Par nicolas.pied dans le forum C++
    Réponses: 1
    Dernier message: 29/11/2005, 18h33

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