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

Bibliothèques C++ Discussion :

Problème de perte de données UDP avec la librairie Poco C++


Sujet :

Bibliothèques C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juin 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2015
    Messages : 5
    Par défaut Problème de perte de données UDP avec la librairie Poco C++
    Bonjour à tous.

    Je suis en train de travailler sur un programme C++ avec la librairie Poco qui me permet d'utiliser les sockets en C++.

    J'aimerais envoyer un vecteur de nombres complexes de taille importante (~10 millions de données) entre 2 ordinateurs. Pour commencer, j'essaye d'envoyer ce vecteur entre 2 ports d'un seul PC.

    Je dois utiliser le protocole UDP pour faire cette transmission (pas de possibilité d'utiliser le protocole TCP).

    Avec le protocole UDP, je suis limité à la taille du buffer d'envoi de données (le maximum étant à un peu moins de 2^16). J'ai donc dû fractionner mon vecteur de données en plusieurs buffers que j'ai envoyés à la suite.

    Comme je le dis dans mon titre, mon problème est que j'ai une perte de données importante à la réception. Je ne récupère que les premiers éléments de chaque buffer (les premiers 1/16 uniquement). Les derniers 15/16 sont des valeurs nulles.

    J'aimerais récupérer la totalité de mes données. Je sais que le protocole UDP n'est pas fiable mais la transmission que je fais actuellement se fait entre 2 ports du MÊME ordinateur. Il n'y devrait pas avoir de perte si je ne dis pas de bêtises.

    Je mets le code source des deux fichiers ci-dessous :

    UDPTransmitter.cpp :

    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
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <complex>
    #include "Poco/Net/SocketAddress.h"
    #include "Poco/Net/DatagramSocket.h"
     
    int main(void) {
     
    	// Creation des variables
    	int transmitterNumberPort = 100;
    	int receiverNumberPort = 102;
    	int tailleBuffer = std::pow(2,15);		// Mettre une puissance de 2 (maximum : 2^15)
    	int nbData = 9.14*std::pow(10,3)*16;
     
    	// Creation des donnees a envoyer
    	std::vector< std::complex<double> > data(nbData);
    	for(int n=0; n<nbData; n++)
    		data[n] = n % (int)std::pow(2,18) + 1.0i;
     
    	try {
    		// Definition des emplacements d'envoi et de reception des donnees
    		Poco::Net::SocketAddress transmitterAddress("localhost", transmitterNumberPort);
    		Poco::Net::SocketAddress receiverAddress("localhost", receiverNumberPort);
     
    		// Creation du socket UDP
    		Poco::Net::DatagramSocket UDPSocket(transmitterAddress,false);
     
    		// Creation des buffers
    		std::vector< std::complex<double> > buffer(tailleBuffer);
     
    		/** Envoi des donnees par paquet **/
    		std::cout << "-- Envoi des donnees --" << std::endl;
    		for(int i=0; i<nbData; i=i+tailleBuffer) {
    			for(int j=i; j<i+tailleBuffer; j++) {
    				// Rembourrage du dernier buffer par des valeurs nulles si 'nbData' n'est pas divisible pas 'tailleBuffer'
    				if(j < nbData)
    					buffer[j-i] = data[j];
    				else
    					buffer[j-i] = 0.0 + 0.0i;
    			}
    			// Envoi des buffers
    			UDPSocket.sendTo(buffer.data(), tailleBuffer, receiverAddress);
     
    			// Verification du fonctionnement du programme
    			if(i == 0) {
    				for(int j=2040;j<2060;j++)
    					std::cout << "buffer[" << j <<"] = " << buffer[j] << std::endl;
    			}
    		}
    	}
    	catch(const Poco::Exception& e) {
    		std::cerr << e.displayText() << std::endl;
    	}
     
    	return 0;
    }

    UDPReceiver.cpp :

    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
    #include <iostream>
    #include <vector>
    #include <complex>
    #include "Poco/Net/SocketAddress.h"
    #include "Poco/Net/DatagramSocket.h"
     
    int main(void) {
     
    	// Creation des variables
    	int transmitterNumberPort = 100;
    	int receiverNumberPort = 102;
    	int tailleBuffer = std::pow(2,15);		// Mettre une puissance de 2 (maximum : 2^15)
    	int nbData = 9.14*std::pow(10,3)*16;
    	int dataLost = 0;
    	double pourcentageDataLost;
    	bool remainingData = true;
    	int cptBuffer = 0;
     
    	// Creation des donnees a recevoir
    	std::vector< std::complex<double> > data(nbData);
     
    	// Creation des donnees qu'on devrait recevoir
    	std::vector< std::complex<double> > dataShouldBeReceived(nbData);
    	for(int n=0; n<nbData; n++)
    		dataShouldBeReceived[n] = n % (int)std::pow(2,18) + 1.0i;
     
    	try {
    		// Definition des emplacements d'envoi et de reception des donnees
    		Poco::Net::SocketAddress transmitterAddress("localhost", transmitterNumberPort);
    		Poco::Net::SocketAddress receiverAddress("localhost", receiverNumberPort);
     
    		// Creation du socket UDP
    		Poco::Net::DatagramSocket UDPSocket(receiverAddress,false);
     
    		// Restriction de la transmission de donnees avec l'emetteur specifie
    		UDPSocket.connect(transmitterAddress);
     
    		// Creation des buffers
    		std::vector< std::complex<double> > buffer(tailleBuffer);
     
    		/** Reception des donnees **/
    		std::cout << "-- Reception des donnees --" << std::endl;
    		// Le PC de reception est sur ecoute tant que tous les paquets ne sont pas arrives.
    		while(remainingData) {
    			// Recuperation des buffers
    			UDPSocket.receiveBytes(buffer.data(), tailleBuffer);
     
    			// Stockage des donnees
    			for(int i=cptBuffer*tailleBuffer; i<(cptBuffer+1)*tailleBuffer; i++) {
    				data[i] = buffer[i-cptBuffer*tailleBuffer];
     
    				// Arret de l'ecoute si toutes les donnees sont arrivees
    				if(i == nbData-1) {
    					remainingData = false;
    					break;
    				}
    			}
     
    			// Incrementation du nombre de buffers
    			cptBuffer++;
    		}
     
    		// Verification du fonctionnement du programme
    		for(int i=2040;i<2060;i++)
    			std::cout << "data[" << i <<"] = " << data[i] << std::endl;
    	}
    	catch(const Poco::Exception& e) {
    		std::cerr << e.displayText() << std::endl;
    	}
     
    	/** Calcul du pourcentage de donnees perdues **/
    	for(int n=0; n<nbData; n++) {
    		if(data[n] != dataShouldBeReceived[n])
    			dataLost++;
    	}
    	pourcentageDataLost = ((double)dataLost/(double)nbData)*100.0;
    	std::cout << "Pourcentage de donnees perdues = " << pourcentageDataLost << " %" << std::endl;
     
    	return 0;
     
    }

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Salut,

    plusieurs choses choquantes
    - tu transfères des float
    - tu transfères 10millions de données
    - le fais en UDP

    Rien que là, on a une triple erreur déjà..
    Transporter des float est une très mauvaise chose, à cause de l'approximation possible sur chaque machine.
    Transporter autant de données est vraiment pas top. Es-tu sur de pas pouvoir les limiter ?
    Transporter ça en UDP est un doux suicide, c'est pas fiable et pas ordonné, et vue la quantité de données que tu trimballes, tu vas surement subir des congestions. Y compris sur un réseau local ou une même machine.
    Je suis surpris que t'aies pas de TCP, il est normalement présent partout au même ordre que UDP.
    En plus POCO ne semble pas fournir de fiabilité ni ordonnancement : pourquoi s'en encombrer ? Ca revient à manipuler un socket UDP vierge, aucun intérêt d'ajouter une lib externe pour ça.
    Elle propose du TCP, pourquoi ne peux-tu pas l'utiliser ?

    -> Tu subis juste des pertes classiques, y'a strictement rien à faire sauf à utiliser TCP ou réimplémenter les mécanismes de TCP sur ton socket.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juin 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2015
    Messages : 5
    Par défaut
    Bonjour,

    Je vous remercie tout d'abord de m'avoir répondu.

    Pour la question du choix entre l'UDP et le TCP, c'est une histoire de matériel. Je dois mettre en place une transmission de données entre 2 cartes réseaux qui sont reliées par une fibre optique. Néanmoins, ce matériel utilise des sockets UDP, d'où mon problème. Et je dois faire avec.

    Le nombre de données peut diminuer mais j'ai toujours le même problème que ce soit avec 10 millions de données ou 1000 données. J'ai toujours la même perte dans la même proportion (15/16 de perte), ce que je trouve assez étrange. En fait, comme je l'ai expliqué dans mon message précédent, j'ai fractionné mon vecteur de données initial en plusieurs buffers que j'envoie à la suite. J'ai donc pensé que c'était plus que la taille des buffers qui jouait un rôle. Mais que je prenne 2^15, 2^10 ou 2^7, cela revient au même.

    En fait, ma problématique de base est de voir jusqu'à quel débit j'arrive à avoir des pertes de données dans la transmission (la fibre optique pouvant transporter 10 Gbps). Mais comme vous le voyez, si j'ai déjà des pertes initiales, je ne vais pas aller bien loin.

    Pour la question de Poco, la vérité c'est qu'on m'a demandé d'utiliser cette librairie pour travailler sur cette tâche et un de mes collègues m'a dit que ça fonctionnait très bien pour l'UDP.

    Je vais essayer de revoir si je n'ai pas d'erreur dans mon programme, car avoir autant de pertes même en envoyant 1000 données semble vraiment étrange.

    Si vous avez des idées, je suis preneur .

    Bonne journée.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    En même temps, vouloir envoyer un datagram de 32768 octets (2^15), c'est...
    https://fr.wikipedia.org/wiki/Maximum_Transmission_Unit
    La perte tourne en général autour de 5%, mais il faut au moins supporter le réordonnancement et pouvoir skip les paquets en doublon.

    Et je parle même pas de ton envoi de vector<complex> sans sérialisation, ou de la taille du buffer spécifié, tailleBuffer, qui est pas du tout correct.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juin 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2015
    Messages : 5
    Par défaut
    Effectivement le 2^15 est peut-être un peu trop important. Je suis descendu à 32 (2^5) pour la taille de mes paquets. Je suis en train de tester avec 64 données au total pour trouver une solution. J'ai donc 2 paquets à envoyer.

    Mais là, toujours le même problème : je ne reçois que les 2 premiers éléments de chaque buffer (le fameux 1/16 de récupéré), ce qui fait 15/16 de perte soit 93,75% de perte... vraiment énorme pour avoir seulement envoyé 64 données. J'en ai conclus que la taille du buffer et des données n'était pas le principal problème.

    Après j'ai regardé en complex int à la place de complex double pour voir s'il y avait une différence. Et effectivement il y a moins de perte, je récupère cette fois-ci les 4 premiers éléments (87,5% de perte). Ensuite j'ai testé en int tout simple, sans complex et j'arrive à obtenir les 8 premiers éléments (75 % de perte). Dois-je vraiment sérialiser mon vector<complex> du coup ?

    Ensuite, pour vérifier les pertes, je compare terme à terme le vecteur de données que je reçois avec le vecteur de données que j'aurais dû recevoir (vecteur de référence). J'ai affiché quelques données reçues pour voir ce qui s'affichaient quand il y avait une perte et je me retrouve avec des données ayant partie réelle et imaginaire nulle. J'avais initialisé mon vecteur de référence avec des données ayant -1 comme partie réelle et imaginaire. Mais elles ont été remplacé par des 0. Donc les 0 sont bien des données remplacées lors de la réception des buffers. Mais je n'arrive toujours pas à comprendre pourquoi.

    Une dernière chose : ce que j'envoie est buffer.data() soit le pointeur sur le premier élément de ce vecteur. Pensez-vous que l'histoire d'ordonnancement vient de là. Au bout d'un envoi de 1/16 des données, l'ordre changerait et ce pointeur serait déplacé autre part ?

    Désolé si mon message n'est pas très compréhensible. Ce n'est pas facile d'expliquer ce problème.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Ton problème semble très simple, c'est du simple envoi de données après tout.. c'est plutôt que tu ne sembles pas savoir utiliser l'API socket.
    Citation Envoyé par BK201_ Voir le message
    Effectivement le 2^15 est peut-être un peu trop important. Je suis descendu à 32 (2^5) pour la taille de mes paquets. Je suis en train de tester avec 64 données au total pour trouver une solution. J'ai donc 2 paquets à envoyer.
    Notre moteur réseau interne envoi un maximum de 1200 octets et est capable de switcher parmi 3 configs pour éviter la congestion. Du coup tu peux aller à 1200 sans risque amha.
    Sachant que ton truc ne tourne que sur ta fibre optique, tu epux certainement aller plus haut, y'a p-e de la doc sur la fibre en question pour te l'indiquer.

    Citation Envoyé par BK201_ Voir le message
    Mais là, toujours le même problème : je ne reçois que les 2 premiers éléments de chaque buffer (le fameux 1/16 de récupéré), ce qui fait 15/16 de perte soit 93,75% de perte... vraiment énorme pour avoir seulement envoyé 64 données. J'en ai conclus que la taille du buffer et des données n'était pas le principal problème.
    Sais-tu que send envoi un buffer, qui est un void*, soit un char* ?
    Que se passe-t-il à ton avis si tu lui demandes d'envoyer data() qui est un tableau contigu de 64 int alors que toi tu lui dis qu'il a 64 octets à envoyer..?
    Bah il t'envoit 64 octets, soit quelques int.
    Etonnament (ou pas), 1/16 c'est à peu près le ratio sizeof(char)/sizeof(complex<double>) (à supposer que complex<double> soit 2 double en interne), donc c'est pas vraiment surprenant ton résultat.

    Citation Envoyé par BK201_ Voir le message
    Après j'ai regardé en complex int à la place de complex double pour voir s'il y avait une différence. Et effectivement il y a moins de perte, je récupère cette fois-ci les 4 premiers éléments (87,5% de perte). Ensuite j'ai testé en int tout simple, sans complex et j'arrive à obtenir les 8 premiers éléments (75 % de perte). Dois-je vraiment sérialiser mon vector<complex> du coup ?
    Etant donné la taille d'un int par rapport à un double, tu as logiquement "moins de perte", n'en reste pas moins que ton algo est mauvais et la taille des données que tu fournis à send comme "à envoyer" n'est pas bonne.

    Citation Envoyé par BK201_ Voir le message
    Une dernière chose : ce que j'envoie est buffer.data() soit le pointeur sur le premier élément de ce vecteur. Pensez-vous que l'histoire d'ordonnancement vient de là. Au bout d'un envoi de 1/16 des données, l'ordre changerait et ce pointeur serait déplacé autre part ?
    Je répète : send envoie un buffer, soit un char*, et la taille à envoyer est en octet. Pas du tout en nombre d'éléments.
    L'ordonnancement n'a rien à voir, c'est juste qu'en UDP, tu peux envoyer 3 paquets, notons A, B et C, et le destinataire recevoir n'importe quelle combinaison de X*A, Y*B, Z*C avec X, Y, Z valant 0+.
    UDP ne fournit qu'une et unique assurance : si ton paquet arrive, il arrive entier. Ou il n'arrive pas.

    Btw, si le buffer de réception est trop petit pour accueillir le datagram, il est silencieusement perdu.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juin 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2015
    Messages : 5
    Par défaut
    D'accord, merci pour cette réponse. Je comprend mieux comment ça marche maintenant. Le "Send" envoie des octets et le buffer ne peut pas être défini comme étant un vector<complex<double>>, il doit être forcément un tableau de char.
    J'avais testé en envoyant un string avant de coder le programme pour le vecteur de données et effectivement je n'avais pas eu de problème de perte à la réception.

    Je vais donc essayé de faire ça :
    - Convertir mon vector en string (avec un format que je vais définir comme mettre des espaces entre les nombres)
    - Fractionner cette string en buffers de taille 1024 par exemple
    - Envoyer ces buffers à la suite avec le "Send"
    - Concaténer les fragments à la réception avec strcat
    - Convertir la string reçue en vector (fonction inverse)

    Il y a peut-être plus simple pour réaliser ceci. Vous avez parlé de sérialisation. J'ai vu qu'il existait des librairies sur le sujet comme "Boost". Est-ce plus simple d'utiliser ceci ? J'ai vu qu'il fallait passer par la création de fichiers (binaires par exemple) mais j'ai l'impression que ce n'est pas vraiment adaptée pour mon cas.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Il faut au moins serializer, et comme je le dis depuis le 1° message : les flottants c'est la merde. Encore que tant que tu restes sur la même machine ça devrait aller, mais par la suite ce sera la merde.
    Donc utiliser Boost pour ça t'épargnera surement des problèmes oui.
    Ne l'ayant jamais utilisé, je ne peux t'en dire plus. Mais la création de fichiers n'a rien à voir, c'est tout juste un détail de serialisation possible.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Il faut au moins serializer, et comme je le dis depuis le 1° message : les flottants c'est la merde. Encore que tant que tu restes sur la même machine ça devrait aller, mais par la suite ce sera la merde.
    Ça peut être raisonnable de considérer que les machines cible supportent les flottants ieee754 double précision. Si ce n’est pas le cas pour une des archis, alors la particularité pourra être traitée à la sérialisation/désérialisation, sur cette machine en particulier. Pour toutes les autres, c’est un bon format de sérialisation vu que c’est très souvent le natif.

  10. #10
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Ça peut être raisonnable de considérer que les machines cible supportent les flottants ieee754 double précision. Si ce n’est pas le cas pour une des archis, alors la particularité pourra être traitée à la sérialisation/désérialisation, sur cette machine en particulier. Pour toutes les autres, c’est un bon format de sérialisation vu que c’est très souvent le natif.
    Le standard n'impose pas le mode d'arrondis il me semble.

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juin 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2015
    Messages : 5
    Par défaut
    Merci pour vos réponses.

    J'ai sérialisé à ma manière pour contrôler ce qu'il se passe. J'ai converti mes vector<complex<double>> en string avec un format spécifique pour pouvoir créer une fonction de désérialisation au niveau du PC récepteur.
    Le programme fonctionne et j'arrive à recevoir toutes les données. Néanmoins, la durée de transmission est devenue très longue forcément. Je vais pouvoir maintenant tester sur une liaison optique entre 2 PC.

    Voici mon programme corrigé :

    UDPTransmitter.cpp :

    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
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <complex>
    #include <string>
    #include "Poco/Net/SocketAddress.h"
    #include "Poco/Net/DatagramSocket.h"
     
    int main(void) {
     
    	// Creation des variables
    	int transmitterNumberPort = 100;
    	int receiverNumberPort = 102;
    	int nbData = 9.14*std::pow(10,2)*16;
    	int tailleBuffer = std::pow(2,10);		// Mettre une puissance de 2 (maximum : 2^15)
    	bool remainingData = true;
    	int cptBuffer = 0;
     
    	// Creation des donnees a envoyer
    	std::vector< std::complex<double> > data(nbData);
    	for(int n=0; n<nbData; n++)
    		data[n] = std::complex<double>((double)(n % (int)std::pow(2,18)), 1.0);
     
    	// Serialisation des donnees a envoyer (vector<complex<double>> => string)
    	// Format : "Partie reelle[0] Partie imaginaire[0] Partie reelle[1] Partie imaginaire[1] ... '\0'"
    	std::string serializedData = "";
    	for(int n=0; n<nbData-1; n++)
    		serializedData += std::to_string(data[n].real()) + ' ' + std::to_string(data[n].imag()) + ' ';
    	// Ajout de 'F' comme marqueur de fin de toute la chaine de caractere
    	serializedData += std::to_string(data[nbData-1].real()) + ' ' + std::to_string(data[nbData-1].imag()) + 'F';
     
    	try {
    		// Definition des emplacements d'envoi et de reception des donnees
    		Poco::Net::SocketAddress transmitterAddress("localhost", transmitterNumberPort);
    		Poco::Net::SocketAddress receiverAddress("localhost", receiverNumberPort);
     
    		// Creation du socket UDP
    		Poco::Net::DatagramSocket UDPSocket(transmitterAddress,false);
     
    		// Creation des buffers
    		char buffer[tailleBuffer];
     
    		/** Envoi des donnees par paquet **/
    		std::cout << "-- Envoi des donnees --" << std::endl;
    		while(remainingData) {
    			// Remplissage des buffers avec les donnees serialisees
    			for(int i=cptBuffer*tailleBuffer; i<(cptBuffer+1)*tailleBuffer; i++) {
    				buffer[i-cptBuffer*tailleBuffer] = serializedData[i];
     
    				// Arret de l'envoi des donnees serialisees si elles ont toutes ete parcourues
    				if(serializedData[i] == 'F') {
    					remainingData = false;
    					break;
    				}
    			}
     
    			// Envoi des buffers
    			UDPSocket.sendTo(buffer, tailleBuffer, receiverAddress);
     
    			// Verification du fonctionnement du programme
    //*			std::cout << "Dernier element du buffer " << cptBuffer << " = " << buffer[tailleBuffer-1] << std::endl;
     
    			// Incrementation du nombre de buffers
    			cptBuffer++;
    		}
    	}
    	catch(const Poco::Exception& e) {
    		std::cerr << e.displayText() << std::endl;
    	}
     
    	return 0;
     
    }

    UDPReceiver.cpp :

    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
    104
    105
    106
    107
    108
    109
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <complex>
    #include <string>
    #include "Poco/Net/SocketAddress.h"
    #include "Poco/Net/DatagramSocket.h"
     
    int main(void) {
     
    	// Creation des variables
    	int transmitterNumberPort = 100;
    	int receiverNumberPort = 102;
    	int nbData = 9.14*std::pow(10,2)*16;
    	int tailleBuffer = std::pow(2,10);		// Mettre une puissance de 2 (maximum : 2^15)
    	bool remainingData = true;
    	int cptBuffer = 0;
    	int cptData = 0;
    	int dataLost = 0;
    	double pourcentageDataLost;
     
    	// Creation des donnees a recevoir
    	std::vector< std::complex<double> > data(nbData);
     
    	// Creation des donnees serialisees a recevoir
    	std::string serializedData = "";
     
    	// Creation des donnees qu'on devrait recevoir
    	std::vector< std::complex<double> > dataShouldBeReceived(nbData);
    	for(int n=0; n<nbData; n++)
    		dataShouldBeReceived[n] = std::complex<double>((double)(n % (int)std::pow(2,18)), 1.0);
     
    	try {
    		// Definition des emplacements d'envoi et de reception des donnees
    		Poco::Net::SocketAddress transmitterAddress("localhost", transmitterNumberPort);
    		Poco::Net::SocketAddress receiverAddress("localhost", receiverNumberPort);
     
    		// Creation du socket UDP
    		Poco::Net::DatagramSocket UDPSocket(receiverAddress,false);
     
    		// Creation des buffers
    		char buffer[tailleBuffer+1];
     
    		/** Reception des donnees **/
    		std::cout << "-- Reception des donnees --" << std::endl;
    		// Le PC de reception est sur ecoute tant que tous les paquets ne sont pas arrives.
    		while(remainingData) {
    			// Recuperation des buffers envoyes par l'emetteur specifie
    			UDPSocket.receiveFrom(buffer, tailleBuffer, transmitterAddress);
     
    			// Ajout de '/0' a la fin de chaque buffer (marqueur de fin des chaines de caracteres)
    			buffer[tailleBuffer] = '\0';
     
    			// Arret de l'ecoute si toutes les donnees sont arrivees
    			for(int i=0; i<tailleBuffer; i++) {
    				if(buffer[i] == 'F') {
    					buffer[i] = '\0';
    					remainingData = false;
    					break;
    				}
    			}
     
    			// Stockage des donnees serialisees
    			serializedData += buffer;
     
    			// Incrementation du nombre de buffers
    			cptBuffer++;
    		}
     
    		// Creation du pointeur sur les donnees serialisees
    		char* pSerializedData = &serializedData[0];
     
    		// Deserialisation des donnees (string => vector<complex<double>>)
    		std::string::size_type sz;
    		while(cptData != nbData) {
    			// Recuperation des parties reelle et imaginaire
    			double partieReelle = std::stod(pSerializedData,&sz);
    			pSerializedData += sz;
    			double partieImaginaire = std::stod(pSerializedData,&sz);
     
    			// Remplissage du vecteur de donnees
    			data[cptData] = std::complex<double>(partieReelle, partieImaginaire);
     
    			// Passage au prochain element
    			pSerializedData += sz;
     
    			// Incrementation du nombre de donnees
    			cptData++;
    		}
     
    		// Verification du fonctionnement du programme
    		for(int i=nbData-11;i<nbData;i++)
    			std::cout << "data[" << i <<"] = " << data[i] << std::endl;
    	}
    	catch(const Poco::Exception& e) {
    		std::cerr << e.displayText() << std::endl;
    	}
     
    	/** Calcul du pourcentage de donnees perdues **/
    	for(int n=0; n<nbData; n++) {
    		if(data[n] != dataShouldBeReceived[n])
    			dataLost++;
    	}
    	pourcentageDataLost = ((double)dataLost/(double)nbData)*100.0;
    	std::cout << "Pourcentage de donnees perdues = " << pourcentageDataLost << " %" << std::endl;
     
    	return 0;
     
    }

Discussions similaires

  1. Perte des données envoyées avec IE
    Par seb76250 dans le forum jQuery
    Réponses: 1
    Dernier message: 31/05/2013, 20h53
  2. Problème connexion base de données MySQL avec VB.net
    Par fridrai dans le forum Administration
    Réponses: 3
    Dernier message: 28/05/2013, 18h59
  3. Problème de consommation de données WCF avec Silverlight
    Par EdouardTH dans le forum Services Web
    Réponses: 0
    Dernier message: 20/05/2011, 14h52
  4. Problème création base de données Access avec C#
    Par VILPELLET dans le forum ADO.NET
    Réponses: 0
    Dernier message: 27/01/2011, 14h33
  5. Dataliste, problème de perte de données
    Par paradeofphp dans le forum ASP.NET
    Réponses: 6
    Dernier message: 15/08/2007, 19h22

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