Problem transmission image BMP par socket C++
Résolu/Fermé
djerem06
Messages postés
50
Date d'inscription
jeudi 5 juin 2008
Statut
Membre
Dernière intervention
23 avril 2015
-
28 juin 2009 à 16:43
djerem06 Messages postés 50 Date d'inscription jeudi 5 juin 2008 Statut Membre Dernière intervention 23 avril 2015 - 30 juin 2009 à 14:27
djerem06 Messages postés 50 Date d'inscription jeudi 5 juin 2008 Statut Membre Dernière intervention 23 avril 2015 - 30 juin 2009 à 14:27
A voir également:
- Problem transmission image BMP par socket C++
- Image iso - Guide
- Acronis true image - Télécharger - Sauvegarde
- Recherche par image - Guide
- Faststone image viewer - Télécharger - Visionnage & Diaporama
- Image iso windows 10 - Guide
5 réponses
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
30 juin 2009 à 10:22
30 juin 2009 à 10:22
Salut.
Et oui, dès fois on se sent seul... (comme toi mes questions trouvent rarement une réponse)
à mon avis, le plus propre c'est d'avoir une reception bloquante, c'est à dire que le read attend l'envoie de nouvelles données du serveur.
Tu peux aussi (peut être) utiliser la valeur retourner la la fonction de lecture.
D'un autre coté, il est très difficile de te répondre car nous n'avons pas tout ton code, et typiquement, il est impossible de trouver ton problème juste avec ce que tu donnes.
En particulier quelles fonction utilises tu pour lire écrire les socket, read ou recv ? quel config de socket etc. ?
Et oui, dès fois on se sent seul... (comme toi mes questions trouvent rarement une réponse)
à mon avis, le plus propre c'est d'avoir une reception bloquante, c'est à dire que le read attend l'envoie de nouvelles données du serveur.
Tu peux aussi (peut être) utiliser la valeur retourner la la fonction de lecture.
D'un autre coté, il est très difficile de te répondre car nous n'avons pas tout ton code, et typiquement, il est impossible de trouver ton problème juste avec ce que tu donnes.
En particulier quelles fonction utilises tu pour lire écrire les socket, read ou recv ? quel config de socket etc. ?
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
30 juin 2009 à 12:49
30 juin 2009 à 12:49
Ok, tout s'explique.
Moi, dans ces cas là, je n'hésite pas à passer outre la classe qui me fait chier et à programmer "bas niveau".
J'ai un peu bidouiller les socket avec Qt (similaire à WxWidget je pense) et je pense que la bonne façon de faire c'est avec les signaux. Je sais que dès que le buffer est près qt:: socket envoie un signal, qu'il suffit alors de connecter avec une fonction qui va lire et mettre en file.
Une question se pose aussi. Es-tu sur que tes paquets arrivent dans l'ordre émis, il me semble qu'il n'y a pas de garanti en TCP IP. Alors il faut faire un accusé de réception à chaque paquet reçut et n'envoyer le suivant que lorsque l'accusé est reçu. Je ne pense pas que ce problème de séquence pose problème sur un réseau local assez peu encombré et de petite taille, mais à l'échelle d'Internet d'un continent à l'autre ?
Moi, dans ces cas là, je n'hésite pas à passer outre la classe qui me fait chier et à programmer "bas niveau".
J'ai un peu bidouiller les socket avec Qt (similaire à WxWidget je pense) et je pense que la bonne façon de faire c'est avec les signaux. Je sais que dès que le buffer est près qt:: socket envoie un signal, qu'il suffit alors de connecter avec une fonction qui va lire et mettre en file.
Une question se pose aussi. Es-tu sur que tes paquets arrivent dans l'ordre émis, il me semble qu'il n'y a pas de garanti en TCP IP. Alors il faut faire un accusé de réception à chaque paquet reçut et n'envoyer le suivant que lorsque l'accusé est reçu. Je ne pense pas que ce problème de séquence pose problème sur un réseau local assez peu encombré et de petite taille, mais à l'échelle d'Internet d'un continent à l'autre ?
djerem06
Messages postés
50
Date d'inscription
jeudi 5 juin 2008
Statut
Membre
Dernière intervention
23 avril 2015
6
30 juin 2009 à 09:37
30 juin 2009 à 09:37
Bon alors personne ne s'est interraissé a mon probléme, ce n'est pas grave, c'est comme ça que j'ai toujour progressé, j'ai réussi a comprendre le pourquoi du comment, donc je donne la solution:
la boucle for de transmission du serveur fait deux choses:
-lire 512 octet dans le fichier
PUIS
-envoyer 512 octets par la socket
la boucle for de transmission du client fait deux chose aussi:
-lire 512 octet par le socket
PUIS
-inscrire cette lecture dans une variable
En l'ocurence, la lecture de 512 octet dans un fichier est une chose bien plus longue que copié 512 octet dans une variable (ROM - RAM)
de ce fait, et c'est une erreur trés béte, le client se remet a lire 512 octet avant que le serveur ne les ai deja emis ! La lecture d'octet n'est pas une opération bloquante, fort heureusement, mais dans mon cas:
for(i=0 ; i < ((taille/NbOctet) + 1) ; i++){
Client.Socket->Read(octet, NbOctet);
for(j = i*NbOctet ; j < (i*NbOctet + NbOctet) ;j++){
Client.contenu[j] = octet[j-i*NbOctet];
}
}
Le client recopi en boucle sa derniere reception de 512 octet dans la variable contenu jusqua se que la lenteur du serveur emette a nouveau.
Pour palier a ce probléme, deux solutions s'offre:
1er) soit on détermine que dans sa boucle for, le client lira un nombre tré inférieur a 512 afin de compenser le temps perdu par le serveur a lire le fichier, ou méme a attendre quelque miliseconde en chaque vague d'emission. (ça c'est une solution absolument vulguére :s dsl mais c juste grace a ça que j'ai aboutis a la seconde)
2nd) entre chaque vague d'emission d'octet, le client li en boucle 1 octet jusqua ce que cette octet lu soit un octet d'AK de la part du serveur, ayant fini de pomper les octet dans le fichier.
de ce fait, le client et le serveur se trouve parfaitement synchronisé, et le client ne lira aucun octet utile dans l'air.
Portion de code (transmission) CLIENT:
char ak=0x19;
unsigned long int ifor = ((taille/NbOctet) + 1);
for(i=0 ; i < ifor ; i++){
do{
Client.Socket->Read(&ak, 1);
}while(ak==0x19);
Client.Socket->Read(octet, NbOctet); //vague de reception
for(j = i*NbOctet ; j < (i*NbOctet + NbOctet) ;j++){
//Client.contenu est une chaine d'octet qui contiendra tou le fichier
Client.contenu[j] = octet[j-i*NbOctet];
}
}
Portion de code, SERVEUR:
char ak=0x91;//valeur totalement arbitraire pourvu quel soit différente de 0x19
for(i=0 ; i<((taille/NbOctet) + 1 ); i++){
re=read(idff, octet, NbOctet);
//lecture dans le fichier terminé, le serveur envoi l'AK, et directement les octet utile
Classe.ecrireOctets(&ak, 1);
re=Classe.ecrireOctets(octet, re);
}
bon bein voila, j'ai faibli a poser la question sur un forum, j'assume en y retournant la solution trouver par ma seul réfléxion.
byebye
la boucle for de transmission du serveur fait deux choses:
-lire 512 octet dans le fichier
PUIS
-envoyer 512 octets par la socket
la boucle for de transmission du client fait deux chose aussi:
-lire 512 octet par le socket
PUIS
-inscrire cette lecture dans une variable
En l'ocurence, la lecture de 512 octet dans un fichier est une chose bien plus longue que copié 512 octet dans une variable (ROM - RAM)
de ce fait, et c'est une erreur trés béte, le client se remet a lire 512 octet avant que le serveur ne les ai deja emis ! La lecture d'octet n'est pas une opération bloquante, fort heureusement, mais dans mon cas:
for(i=0 ; i < ((taille/NbOctet) + 1) ; i++){
Client.Socket->Read(octet, NbOctet);
for(j = i*NbOctet ; j < (i*NbOctet + NbOctet) ;j++){
Client.contenu[j] = octet[j-i*NbOctet];
}
}
Le client recopi en boucle sa derniere reception de 512 octet dans la variable contenu jusqua se que la lenteur du serveur emette a nouveau.
Pour palier a ce probléme, deux solutions s'offre:
1er) soit on détermine que dans sa boucle for, le client lira un nombre tré inférieur a 512 afin de compenser le temps perdu par le serveur a lire le fichier, ou méme a attendre quelque miliseconde en chaque vague d'emission. (ça c'est une solution absolument vulguére :s dsl mais c juste grace a ça que j'ai aboutis a la seconde)
2nd) entre chaque vague d'emission d'octet, le client li en boucle 1 octet jusqua ce que cette octet lu soit un octet d'AK de la part du serveur, ayant fini de pomper les octet dans le fichier.
de ce fait, le client et le serveur se trouve parfaitement synchronisé, et le client ne lira aucun octet utile dans l'air.
Portion de code (transmission) CLIENT:
char ak=0x19;
unsigned long int ifor = ((taille/NbOctet) + 1);
for(i=0 ; i < ifor ; i++){
do{
Client.Socket->Read(&ak, 1);
}while(ak==0x19);
Client.Socket->Read(octet, NbOctet); //vague de reception
for(j = i*NbOctet ; j < (i*NbOctet + NbOctet) ;j++){
//Client.contenu est une chaine d'octet qui contiendra tou le fichier
Client.contenu[j] = octet[j-i*NbOctet];
}
}
Portion de code, SERVEUR:
char ak=0x91;//valeur totalement arbitraire pourvu quel soit différente de 0x19
for(i=0 ; i<((taille/NbOctet) + 1 ); i++){
re=read(idff, octet, NbOctet);
//lecture dans le fichier terminé, le serveur envoi l'AK, et directement les octet utile
Classe.ecrireOctets(&ak, 1);
re=Classe.ecrireOctets(octet, re);
}
bon bein voila, j'ai faibli a poser la question sur un forum, j'assume en y retournant la solution trouver par ma seul réfléxion.
byebye
djerem06
Messages postés
50
Date d'inscription
jeudi 5 juin 2008
Statut
Membre
Dernière intervention
23 avril 2015
6
30 juin 2009 à 12:24
30 juin 2009 à 12:24
Salut et merci de t'interraissé a mon projet.
alors le souci c'est que le Client j'ai voulu le fair en wxWidget pour pouvoir bénéficier de sa simplicité de mise en euvre et surtout que le code peu étre compilé pour UNIX, et donc pour respecter ce wxWidget, j'ai du utiliser le Read et le Write de WxSocketBase (je crois) et ces méthode ne renvoyent pas le nombre d'octet effectivement lu ou ecri ! sa va de pair avec le fait qu'elle ne sont pas bloquante...
aprés pour le serveur (qui ne tournera que sur du Windob), j'ai utiliser les socket normal, jte fait un copier coller des lignes concerné:
-WSAStartup(MAKEWORD(2,0), &WSAData);
-socket (AF_INET, SOCK_STREAM, 0);
-idServeur.sin_family = AF_INET;
idServeur.sin_port = htons (PORT); //N° de port
idServeur.sin_addr.s_addr = htonl (INADDR_ANY); //Adresse IP
c'est vrai que j'ai laisser les méthode maison ecrirOctet et liceOctet, donc je me ser de:
recv et send
qui sont bien bloquant et renvoient le nombre d'octet effectivement lu ou ecrit, ce qui n'est pas le cas de Socket->Read et Socket->Write qui sont les deux méthode équivalente en wx (client)
c'est sur qu'avec un client et serveur équipé de méthode bloquante de lecture et ecriture d'octet sur le reseau, le problem ne se poserais pas, mais finalement je me suis dit qu'attendre le AK entre chaque volé, c'été un peu plus respectueux envers mon propre protocol d'échange :p
Bon donc du coup sa fonctionne a la perfection :)
alors le souci c'est que le Client j'ai voulu le fair en wxWidget pour pouvoir bénéficier de sa simplicité de mise en euvre et surtout que le code peu étre compilé pour UNIX, et donc pour respecter ce wxWidget, j'ai du utiliser le Read et le Write de WxSocketBase (je crois) et ces méthode ne renvoyent pas le nombre d'octet effectivement lu ou ecri ! sa va de pair avec le fait qu'elle ne sont pas bloquante...
aprés pour le serveur (qui ne tournera que sur du Windob), j'ai utiliser les socket normal, jte fait un copier coller des lignes concerné:
-WSAStartup(MAKEWORD(2,0), &WSAData);
-socket (AF_INET, SOCK_STREAM, 0);
-idServeur.sin_family = AF_INET;
idServeur.sin_port = htons (PORT); //N° de port
idServeur.sin_addr.s_addr = htonl (INADDR_ANY); //Adresse IP
c'est vrai que j'ai laisser les méthode maison ecrirOctet et liceOctet, donc je me ser de:
recv et send
qui sont bien bloquant et renvoient le nombre d'octet effectivement lu ou ecrit, ce qui n'est pas le cas de Socket->Read et Socket->Write qui sont les deux méthode équivalente en wx (client)
c'est sur qu'avec un client et serveur équipé de méthode bloquante de lecture et ecriture d'octet sur le reseau, le problem ne se poserais pas, mais finalement je me suis dit qu'attendre le AK entre chaque volé, c'été un peu plus respectueux envers mon propre protocol d'échange :p
Bon donc du coup sa fonctionne a la perfection :)
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
djerem06
Messages postés
50
Date d'inscription
jeudi 5 juin 2008
Statut
Membre
Dernière intervention
23 avril 2015
6
30 juin 2009 à 14:27
30 juin 2009 à 14:27
Excellente remarque ! j'ador!
effectivement je n'ai aucune garantis que les packet arrive dans l'ordre, il faudrais dédié les deux premier octet de chaque packet a contenir une valeur entiére incrémenté par le serveur entre chaque emission, et le client remettrais alors en ordre tout seul les packet a la fin de la transmission, ou comme tu dis, un AK entre chaque echange qui serais un transfére un poil plus long, mais plus simple a coder.
En revanche mon réseau famillial ne contient qu'un seul et unique neud entre 2 ordinateur, je ne risque donc pas la tempéte de broadcast (lol) et c'est pour sa que je ne me suis pas penché sur l'ordre des paquets (je me serais peu étre fait avoir :p)
en revanche j'ai souvent eu l'idé que tu réveille en moi: coder un client serveur qui s'entendent d'un continent a l'autre. mais ne divaguons pas sur ce topic :p
si tu es comme moi pationné de c++ et réseaux, ouvrons un topic privé sur ce sujet (?)
effectivement je n'ai aucune garantis que les packet arrive dans l'ordre, il faudrais dédié les deux premier octet de chaque packet a contenir une valeur entiére incrémenté par le serveur entre chaque emission, et le client remettrais alors en ordre tout seul les packet a la fin de la transmission, ou comme tu dis, un AK entre chaque echange qui serais un transfére un poil plus long, mais plus simple a coder.
En revanche mon réseau famillial ne contient qu'un seul et unique neud entre 2 ordinateur, je ne risque donc pas la tempéte de broadcast (lol) et c'est pour sa que je ne me suis pas penché sur l'ordre des paquets (je me serais peu étre fait avoir :p)
en revanche j'ai souvent eu l'idé que tu réveille en moi: coder un client serveur qui s'entendent d'un continent a l'autre. mais ne divaguons pas sur ce topic :p
si tu es comme moi pationné de c++ et réseaux, ouvrons un topic privé sur ce sujet (?)