Votre question

[résolu] C++ et les horribles \0\0

Tags :
  • Serveur
  • Programmation
Dernière réponse : dans Programmation
Anonyme
27 Janvier 2008 13:31:21

Bonjour,

J'ai ecrit un programme serveur en C++ ( sous Dev Cpp ) et un programme client en VB 6.0. Ils marchent ( sisi ) mais il y a un probleme, car quand VB envoie une chaine avec :

  1. frmClient.Socket.SendData 1


le serveur recoit :

  1. 1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0...


Or dans mon code en C++ il est ecrit :

  1. if(buffer=="1")
  2. {
  3. send(sock,"reponse",sizeof("reponse"),0);
  4. }


donc buffer!=1 :( 

Comment puis j'enlever ces horribles zeros ???

Autres pages sur : resolu horribles

Anonyme
27 Janvier 2008 14:19:21

Salut
tu devrais plutot poster le receive du serveur, voir le code du serveur entier si possible (sur past bin)
a b L Programmation
27 Janvier 2008 14:40:55

si "buffer" est de type char *, ton test ne fait qu'une comparaison de pointeur (qui sont forcément toujours différents). En utilisant le strcmp, ça compare jusqu'au \0:

  1. if( strcmp(buffer, "1") == 0 )
  2. {
  3. send(sock,"reponse",sizeof("reponse" ),0);
  4. }


Et pense au '\0' pour les tailles des paquets envoyés.
Contenus similaires
Pas de réponse à votre question ? Demandez !
Anonyme
27 Janvier 2008 15:19:24

CRicky a dit :

Et pense au '\0' pour les tailles des paquets envoyés.


C'est a dire ?
a b L Programmation
27 Janvier 2008 16:57:37

pour envoyer une chaine de caractères, il faut envoyer aussi le \0, sinon tu ne saura pas quand ta chaine finira, sauf si tu envoies la taille juste avant :) 
Anonyme
27 Janvier 2008 17:00:10

Mais de toute facon le VB ne remplira pas le reste avec des \0 tout moches ?
Et puis pendant que t'est la, pour envoyer un fichier il faut que je l'ouvre ne binaire et que j'envoye son contenu ( en bianire ) pour le recevoir et le placer dans un autre fichier ca sera ca a peu pres ?
a b L Programmation
27 Janvier 2008 17:21:34

Côté VB, je pense que ça dépend de la taille des buffers, mais je ne connais pas les sockets en VB, utilises-tu les fonctions de la win32 API ?
Pour le fichier c'est bien ça, mais je te conseille d'envoyer la taille des données qui suivent, car ça peut arriver en plusieurs fois.
Anonyme
27 Janvier 2008 17:41:46

Non j'ai ecrit cette fonction pour traiter les données rentrantes il pour un autre de mes programmes qui est un client et un serveur VB :

  1. Sub IncomingData(ByVal DataLength As Long)
  2. Dim buffer() As Byte
  3. Dim data As String
  4. Dim parse() As String
  5. On Error Resume Next
  6.  
  7. If ok = False Then ' est ce une demande ou un fichier qui arrive ?
  8. DAFORM.Socket.GetData data, vbString, DataLength
  9.  
  10. parse = Split(data, SEP_CHAR)
  11.  
  12. parse(0) = LCase(parse(0))
  13.  
  14. If parse(0) = "file" Then
  15. If parse(1) = "" Then Exit Sub
  16. FileName = DAFORM.txtPath.Text & "\" & parse(1)
  17. DaFile = parse(1)
  18. Open FileName For Binary As #2
  19. DAFORM.ProgressBar1.Max = parse(2)
  20. ok = True
  21. Else
  22. DAFORM.Command1.Enabled = True
  23. End If
  24. Else 'si c'est le fichier qui arrive
  25.  
  26. DAFORM.Socket.GetData buffer
  27. Put #2, pos, buffer
  28. DAFORM.lblConnection.Caption = "Telechargement en cours ! " & Int((DAFORM.ProgressBar1.Value / DAFORM.ProgressBar1.Max) * 100) & " % recus."
  29. pos = pos + UBound(buffer) + 1
  30. DAFORM.ProgressBar1.Value = DAFORM.ProgressBar1.Value + DataLength
  31. If DAFORM.ProgressBar1.Value = DAFORM.ProgressBar1.Max Then Close #2: DAFORM.lblConnection.Caption = "Telechargement terminé !": ok = False: pos = 1: DAFORM.Command1.Enabled = True: DAFORM.Command2.Enabled = False: MsgBox "Le fichiera bien été mis a jour !": Shell DaFile: End
  32. End If
  33. End Sub


Comme ca quel que soit la taille des packets recus on a commeme un fichier compet a la fin.

Et coté serveur c'set tout bete :

  1. frmServer.Socket(index).SendData Buffer
  2. DoEvents


Mais esque en C++ le coté serveur sera pareil ??? ( ca marrangerait xD )
a b L Programmation
27 Janvier 2008 18:29:59

Les Socket fonctionnent au niveau de l'OS, donc le fonctionnement est le même quel que soit le langage.
Peut-être qu'en VB il y a une surcouche, mais je ne crois pas. Je pense que le comportement en C++ est le même.

Dans ton exemple 100% VB, tu n'as pas de problème si tu envoies un fichier qui dépasse les 64ko ?
Anonyme
27 Janvier 2008 18:32:37

nono c'est le programme pour mettre a jour l'exe de mon MMORPG et il fonctionne nickel :) 

Puisque il rajoute au fichier les packets de 64k tant que c'est pas la fin.
If DAFORM.ProgressBar1.Value = DAFORM.ProgressBar1.Max
a b L Programmation
27 Janvier 2008 18:44:45

Ah oui, j'avais pas bien lu. Donc, le même principe est à faire en C++.

S'il y a des \0 en trop à cause de VB, ce n'est pas bien grave si, en C++, tu conserves le même protocole que tu as définis dans ton code VB.
Anonyme
27 Janvier 2008 18:45:11

ok merci beaucoup
Anonyme
29 Janvier 2008 01:39:12

Je continue le post :

Donc j'ai un probleme c'est que mon programme serveur n'arrive pas a detecter que le client s'est deconnecté, donc le socket n'est plus en ecoute et au bout de deux connexion a mon programme serveur celui ci se bloque, voici le code

  1. // Si les sockets Windows fonctionnent
  2. if(!erreur)
  3. {
  4. sock = socket (AF_INET, SOCK_STREAM, 0);
  5. // Si la socket est valide
  6. if (sock != INVALID_SOCKET)
  7. {
  8. printf ("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
  9. sin.sin_addr.s_addr = htonl (INADDR_ANY); // Adresse IP automatique
  10. sin.sin_family = AF_INET; // protocole familial (IP)
  11. sin.sin_port = htons (7777); // listage du port
  12.  
  13. while(1)
  14. {
  15.  
  16. //sock_err = bind (sock, (SOCKADDR *) &sin, sizeof sin);
  17. sock_err = listen (csock, 5);
  18.  
  19. //Si la socket fonctionne
  20. if (sock_err != SOCKET_ERROR)
  21. {
  22. // démarrage du listage (mode server)
  23. sock_err = listen (sock, 5);
  24. printf ("Listage du port %d...\n", 7777);
  25. //Si la socket fonctionne
  26. if (sock_err != SOCKET_ERROR)
  27. {
  28. // Attente pendant laquelle le client se connecte
  29. printf ("Ecoute sur le port 7777...\n");
  30. csin.sin_addr.s_addr = htonl(7777);
  31. csin.sin_family = AF_INET;
  32. csin.sin_port = htons(7777);
  33.  
  34. if((csock = accept (sock, (SOCKADDR *) &csin, &recsize))!=INVALID_SOCKET)
  35. {
  36. printf ("Un client se connecte avec la socket %d de %s:%d\n", csock, inet_ntoa (csin.sin_addr), htons (csin.sin_port));
  37. sock_err = send(csock, buffer, sizeof(buffer), 0);
  38.  
  39. while(sock_err != SOCKET_ERROR)
  40. {
  41. sock_err = listen (csock, 5);
  42. if (sock_err==0)
  43. {
  44. csock = accept (sock, (SOCKADDR *) &csin, &recsize)!=INVALID_SOCKET ;
  45. }
  46. memset(buffer,0,sizeof(buffer));
  47. recv(csock,buffer,sizeof(buffer),0);
  48. printf("%s",buffer);
  49. if(strcmp(buffer,"1")==0)
  50. {
  51. send(csock, buffer, sizeof(buffer), 0);
  52. }
  53. }
  54. }
  55. else
  56. {
  57. printf("Socket fermé.\n");
  58. shutdown (csock, 2);
  59. }
  60. }
  61. //Il ne faut pas oublier de rompre la connexion (fermée dans les deux sens)
  62. }
  63. }
  64.  
  65.  
  66. // fermeture de la socket
  67. printf ("Fermeture de la socket...\n");
  68. sock_err = closesocket(sock);
  69. printf ("Fermeture du serveur terminee\n");
  70. }


Ce code est basé sur l'exemple du site du zero.

EDIT:
En faite ce que je voudrais c'est que le serveur ferme le socket a la perte de connexion avec le client ( coupure d'internet ) et qu'il reouvre immediatement le socket pour que le client puisse se reconnecter mais au bout de deux connection le serveur bug et reponds plus :( 

A mon humble avis c'est sock_err = listen (csock, 5); qui ne va pas, mais je ne sais pas comment le remplacer pour verifier si le client est toujours connecté !

Ps: Vive le VB franchement !

If Socket.State <> sckConnected Then
MsgBox "Client deconnecté !", vbInformation, "Erreur !"
End If

Et voilaaaaaaaaaaa, et en C/C++ il faut chercher dans une disaine de manuels pour trouver son bonheur xD
a b L Programmation
29 Janvier 2008 21:03:15

Il faut tester le retour de "recv":
- Si >0, c'est le nombre d'octets reçus
- Si ==0, la connexion est coupée
- Si <0, il y a une erreur socket
Même chose sur le "send"

Les listen et accept, c'est juste pour établir une connexion. Le accept est bloquant jusqu'à ce qu'un client se connecte sur le port écouté. A ce niveau, rien n'est connecté.
C'est send et recv qui font la communication, c'est donc sur eux qu'il faut tester si la communication est toujours présente. Le recv est bloquant en lecture, mais peut être débloqué si une erreur de connexion ou une perte de connexion se produit.

En VB c'est simple, mais en fait plus complexe parce que c'est une surcouche des sockets ;) 
Anonyme
30 Janvier 2008 12:41:37

J'ai trouvé ! Au lieu de chercher dans des bouquins ennuyeux, il faut demander a CRicky :) 

Merci beaucoup, ca marche parfaitement bien.
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS