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 :

[SOCKETS] Conseils pour l'envoi d'un tableau de floats par socket


Sujet :

C++

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Points : 61
    Points
    61
    Par défaut [SOCKETS] Conseils pour l'envoi d'un tableau de floats par socket
    Salut !

    Je me trouve devant un petit problème et je cherche des conseils donc je suis venu demander ici ...

    J'ai une machine d'acquisition qui envoie à mon PC un tableau de floats. Je récupère ce tableau dans un programme client, et je souhaite l'envoyer à un programme serveur.

    Vu qu'il s'agit juste d'un tableau de float j'ai penché pour le choix des sockets (j'ai vu qu'on pouvait facilement les rendre portables avec quelques librairies, ou simplement des #ifdef ...). J'avais aussi pensé à un ORB mais ça fait peut-être un peu lourd juste pour un envoi de tableau. En plus il me faut un envoie assez rapide, le but est de se rapprocher du temps réel (est-ce que les ORB sont moins rapide? ça je ne sais pas ...)

    Bon mon problème est que j'insère mon tableau de floats dans un flot (je les sépare par des ; pour les différencier), puis j'envoie le char* correspondant par socket à mon serveur ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::ostringstream oss;
    for(int i=0; i < nbCol; i++){
    	oss << (float)fData[i] << ";";
    }
    oss << "\r\n";
    std::string result = oss.str();
    send(Acquisition::sock, result.c_str(), result.size(), 0);
    Jusque là ça marche bien ...
    Si j'essaye de relire de suite mon float ça marche parfaitement aussi ...

    Par contre côté serveur j'ai un problème ...
    Si je mets une tempo après le send tout se passe bien, il envoi de suite la ligne lue et c'est parfait ...
    Si par contre je n'ai pas de tempo (ce qui est le but vu que je veux du temps réel) il envoi plus vite que je ne lis, et du coup il accumule les lignes dans un buffer. Du coup il charge parfois dans le buffer un début de ligne (en fin de buffer) et la fin est chargée au coup d'après.

    Je voulais savoir comment je pourrais parser facilement du côté serveur mon flot (sachant que chaque ligne fait toujours le même nombre de floats durant une exécution) sans avoir le problème de lignes coupées, et si possible avec une méthode me débarassant d'un caractère de séparation ...

    Je sais c'est peut-être pas très bien expliqué ... j'espère que j'ai tout de même réussit à être le plus clair possible ...

  2. #2
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    d'abord, plutôt que de mettre "\r\n", essaye de mettre std::endl.
    La différence, c'est que std::endl t'assure que tout est flushé après l'instruction std::cout << std::endl.

    Ensuite, côté serveur, il faudrait que tu montres le code qui lit dans la socket.
    tu fais comment ? std::cin ? std::get_line() ? etc....

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Points : 61
    Points
    61
    Par défaut
    Justement je pense que mon code serveur n'est pas correct ... c'est pour ça que je voulais savoir s'il y avait une bonne méthode pour récupérer ces infos envoyées ...

    En premier lieu je faisais ça : (mais je suis en train de tout reprendre pour trouver une méthode qui marche ...)

    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
     
    int j = 0;
    int k = 0;
    char tmp[256];
    for(k=0; k<256; k++) tmp[k] = '\0';
    SOCKET acceptation; //ouvert avant dans le code
    char tampon[1024];
    float data[NBELEC]; // NBELEC défini avant et vaut 14 dans le premier jet ... (et égal au NbCol du client)
     
    while(1){
    	lire = recv(acceptation, tampon, sizeof(tampon), 0);
    	if(lire != -1){
    		for(int i =0; i < 1024 && tampon[i] != '\0'; ++i){
    			if(tampon[i] == ';'){
    				data[j] =  (float)atof(tmp);
    				j = (j+1)%NBELEC;
    				if (j == 0){
    					for(int a = 0; a < NBELEC; ++a) std::cout << data[a] << " - ";
    					std::cout << std::endl;
    				}
    				for(k=0; k<256; k++) tmp[k] = '\0'; 
                                    //Peut être que le iss >> data[j] s'arrête au premier \0 rencontré ? et dans ce cas il suffit de rajouter un \0 à la fin
    				k = 0;
    			} else {
    				tmp[k++] = tampon[i];
    			}
    		}
    	}
    }
    Je sais le code n'est pas propre du tout ...
    Mais c'est un premier jet juste pour essayer.

    Actuellement j'essaye de passer par un ostringstream mais il faut que je récup ma machine pour essayer mon code dans l'après midi

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Points : 61
    Points
    61
    Par défaut
    Bon la seconde version foire totalement elle ne sort rien de correct ...

    Retour à la version précédente ... j'ai réussit à la débeuger, il suffisait que je lise le nombre de caractère lus dans le tampon et pas tout le tampon (je sais je suis un boulet :/ )

    Merci encore

    Et si vous avez des conseils à me donner concernant les transfert temps réels de tableaux je suis preneur !

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Points : 61
    Points
    61
    Par défaut
    Salut ! C'est encore moi je sais ...

    Maintenant l'envoi marche bien et la réception aussi ... tant que le client et le servuer tournent sur la même machine et que je mette "localhost" pour l'adresse du serveur ...

    Dès que je mets le nom de ma machine dans l'adresse du destinataire ça ne marche plus. Il a l'air de bien faire la résolution DNS mais il plante à l'ouverture du socket ...

    Mon code 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
     
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);
     
    SOCKADDR_IN emetteur;
    SOCKADDR_IN hote;
     
    HOSTENT* host = gethostbyname("localhost");
    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;}  
     
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == INVALID_SOCKET){
    	std::cout << "Erreur à l'ouverture du socket" << std::endl;
    	return false;
    } 
    if(bind(sock, (SOCKADDR*)&hote, sizeof(hote)) == SOCKET_ERROR){
    	std::cout << "Erreur lors du bind du socket" << std::endl;
    	return false;
    } 
    std::cout << "Socket created and binded" << std::endl;
     
    std::cout << "Waiting connection" << std::endl;
    listen(sock,1);
     
    int val = (int)(sizeof(emetteur));
    acceptation = accept(sock, (SOCKADDR*)&emetteur, &val);
     
    std::cout << "Connected" << std::endl;
    if(acceptation == INVALID_SOCKET) {
    	std::cout << "Erreur lors de l'ouverture de la connexion" << std::endl;
    	return false;
    }
    Mon 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
     
    bool res = true;
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);
     
    char* nomDest = NULL;
    int port;
     
    if(argc == 5){
    	if(!strcmp(argv[1],"-host") && !strcmp(argv[3],"-port")){
    		nomDest = argv[2];
    		port = atoi(argv[4]);
    	} else if(!strcmp(argv[3],"-host") && !strcmp(argv[1],"-port")){
    		nomDest = argv[4];
    		port = atoi(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 = atoi(argv[2]);
    	}
    } else if(argc == 1) {
    	nomDest = "localhost";
    	port = 9999;
    } else {
    	usage(argv[0]);
    	res = false;
    }
     
    if (res){
    	// Résolution DNS à partir du nom de la machine
    	HOSTENT* host = gethostbyname(nomDest);
    	//Initialisation de la structure sockaddr_in	
    	SOCKADDR_IN destinataire;
    	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 == INVALID_SOCKET){
    		std::cerr << "Erreur à l'ouverture du socket" << std::endl;
    		res = false;
    	} else std::cerr << "Socket ouvert" << std::endl;
     
    	int connecte = connect(sock, (SOCKADDR*)&destinataire, sizeof(destinataire));
    	if(connecte == SOCKET_ERROR){	
    		std::cerr << "Echec de la connexion à " << nomDest << " - " << connecte << std::endl;
    		res = false;
    	} else {
    		std::cout << "Connecté" << std::endl;
    	}
    }

    Le serveur se met bien en attente de connexion, mais le client rente -1 pour le connecte quand je lui mets le nom de la machine pour nomDest (en l'occurence "cariboux.irisa.fr" en ce moment qui est aussi "localhost")

    Par contre il se connecte bien quand je lui met "localhost" et pas le nom de la machine

    Edit :

    Avec debug voilà la structure de host pour les valeurs de nomDest :
    • localhost :
      • h_name : 0x00355708 "cariboux.irisa.fr"
      • h_addrtype : 2
      • h_length : 4
      • h_addr_list : 0x003556fc
        • 0x00355704 ""
          • 127 ''


    • cariboux.irisa.fr (qui est localhost) :
      • h_name : 0x00355708 "cariboux.irisa.fr"
      • h_addrtype : 2
      • h_length : 4
      • h_addr_list : 0x003556fc
        • 0x00355704 : "ƒþJcariboux.irisa.fr"
          • -125 'ƒ'






    Cj'ai l'impression que le gethostbyname ne rend pas la même chose pour h_addr_list si l'on met localhost ou le nom de la machine

    Edit 2 : Bon j'ai testé et en fait le gethostbyname rend la bonne adresse IP dans host pourtant ...

    Help je comprend vraiment pas où ça plante ...

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 117
    Points : 61
    Points
    61
    Par défaut
    Bon j'ai trouvé le problème mais je ne sais pas comment le résoudre en fait ...

    Si je donne à mon serveur le nom de machine localhost et à mon client localhost aussi ça marche ...
    Si je donne à mon serveur le nom de machine "cariboux" et à mon client localhost aussi ça ne marche pas ...
    Si je donne à mon serveur le nom de machine localhost et à mon client "cariboux" aussi ça ne marche pas ...
    Si je donne à mon serveur le nom de machine "cariboux" et à mon client "cariboux" aussi ça marche ...

    En gros quelle méthode est-ce que je dois utiliser ?

    Ne jamais utiliser localhost mais utiliser gethostname(...) à la place ?
    Sauf que si je ne me trompe pas getshost name va renvoyer le nom de la machine, et donc les commmunications se feront par le réseau même si le client et le serveur sont sur la même machine non ? (vu qu'il utilisera l'adresse IP et no nplus l'adresse 127.0.0.1 non routable ...)

Discussions similaires

  1. [HTML 4.0] Conseils pour faire un site en tableau
    Par d-85a dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 05/04/2009, 14h39
  2. Envoi d'une capture d'ecran par socket
    Par manu225 dans le forum C++Builder
    Réponses: 5
    Dernier message: 22/01/2007, 15h59
  3. [Mail] Besoin d'un conseil pour l'envoi d'e-mail
    Par olive_le_malin dans le forum Langage
    Réponses: 1
    Dernier message: 21/12/2006, 11h39
  4. Cherche conseil pour l'envoi de fichiers
    Par ehmppowa dans le forum Applets
    Réponses: 4
    Dernier message: 17/01/2006, 13h39
  5. [Socket] Envoi de texte et d'objets par socket
    Par ced dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 05/08/2004, 09h07

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