Tom's Guide > Forum > Programmation > [résolu] C++ et les horribles \0\0

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

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

TomsGuide.com : 800 000 inscrits répondent à toutes vos questions high-tech et informatique. Pour obtenir de l'aide, inscrivez-vous gratuitement !
Mot :    Pseudo :           
 

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 :

Code :
  1. frmClient.Socket.SendData 1



le serveur recoit :

Code :
  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 :

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



donc buffer!=1 :(

Comment puis j'enlever ces horribles zeros ???


Message édité par Hrusdik le 27-01-2008 à 18:48:35
------------------------------ Codialement, Hrusdik.
Liens sponsorisés
Inscrivez-vous ou connectez-vous pour masquer ceci.

Salut
tu devrais plutot poster le receive du serveur, voir le code du serveur entier si possible (sur past bin)


Message édité par Anonyme le 27-01-2008 à 14:19:39
Répondre à Anonyme

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:

Code :
  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.

------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

CRicky a écrit :


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



C'est a dire ?

------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik

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 :)

------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

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 ?

------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik

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.

------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

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 :

Code :
  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.             parse = Split(data, SEP_CHAR)
  10.             parse(0) = LCase(parse(0))
  11.            
  12.             If parse(0) = "file" Then
  13.                 If parse(1) = "" Then Exit Sub
  14.                 FileName = DAFORM.txtPath.Text & "\" & parse(1)
  15.                 DaFile = parse(1)
  16.                 Open FileName For Binary As #2
  17.                 DAFORM.ProgressBar1.Max = parse(2)
  18.                 ok = True
  19.             Else
  20.                 DAFORM.Command1.Enabled = True
  21.             End If
  22.     Else 'si c'est le fichier qui arrive
  23.            
  24.         DAFORM.Socket.GetData buffer
  25.         Put #2, pos, buffer
  26.         DAFORM.lblConnection.Caption = "Telechargement en cours !  " & Int((DAFORM.ProgressBar1.Value / DAFORM.ProgressBar1.Max) * 100) & " % recus."
  27.         pos = pos + UBound(buffer) + 1
  28.         DAFORM.ProgressBar1.Value = DAFORM.ProgressBar1.Value + DataLength
  29.         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
  30.     End If
  31. 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 :

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



Mais esque en C++ le coté serveur sera pareil ??? ( ca marrangerait xD )

------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik

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 ?

------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

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

------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik

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.

------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

ok merci beaucoup

------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik

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

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.                     if((csock = accept (sock, (SOCKADDR *) &csin, &recsize))!=INVALID_SOCKET)
  34.                     {
  35.                     printf ("Un client se connecte avec la socket %d de %s:%d\n", csock, inet_ntoa (csin.sin_addr), htons (csin.sin_port));
  36.                     sock_err = send(csock, buffer, sizeof(buffer), 0);
  37.                       while(sock_err != SOCKET_ERROR)
  38.                         {
  39.                           sock_err = listen (csock, 5);
  40.                           if (sock_err==0)
  41.                           {
  42.                               csock = accept (sock, (SOCKADDR *) &csin, &recsize)!=INVALID_SOCKET      ;     
  43.                           }
  44.                           memset(buffer,0,sizeof(buffer));
  45.                           recv(csock,buffer,sizeof(buffer),0);
  46.                           printf("%s",buffer);
  47.                           if(strcmp(buffer,"1" )==0)
  48.                             {
  49.                                 send(csock, buffer, sizeof(buffer), 0);
  50.                                 }
  51.                         }
  52.                     }
  53.                     else
  54.                       {
  55.                         printf("Socket fermé.\n" );
  56.                         shutdown (csock, 2);
  57.                       }
  58.                     }
  59.                     //Il ne faut pas oublier de rompre la connexion (fermée dans les deux sens)
  60.               }
  61.               }
  62.        
  63.            
  64.             // fermeture de la socket
  65.             printf ("Fermeture de la socket...\n" );
  66.             sock_err = closesocket(sock);
  67.             printf ("Fermeture du serveur terminee\n" );
  68.         }



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


Message édité par Hrusdik le 29-01-2008 à 20:15:55
------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik

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 ;)

------------------------------ 6800A007B81300CD10B00131C989CF26880541
81F900FA750230EDBADA03ECA80875FBECA808
74FBE4603C0175DFB80300CD10B8004CCD21
Répondre à CRicky

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

Merci beaucoup, ca marche parfaitement bien.

------------------------------ Codialement, Hrusdik.
Répondre à Hrusdik
Tom's Guide > Forum > Programmation > [résolu] C++ et les horribles \0\0
Aller à :

Il y a 1682 utilisateurs connus et inconnus. Pour voir la liste des connectés connus, cliquez ici.

Attention

Vous allez répondre sur un sujet resté inactif pendant plus de 6 mois.
Assurez-vous d'apporter des éléments nouveaux à la discussion avant de poursuivre.

Répondre Annuler
Liens