Comportement recv de Winsock etrange

thejojo1 Messages postés 13 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 28 août 2006 - 28 août 2006 à 15:46
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 - 28 août 2006 à 22:56
Salut jespere quun spécialiste de winsock va pouvoir maider! Voila je programme un serveur ftp et tout marche... en reseau local! Sur internet c'est une autre affaire. En fait je rencontre une erreur lors de l'upload d'un fichier. Il semble que certains paquets soient envoyés 2 fois. Voici le code qui pose problème:

LRESULT CALLBACK ProcessMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 switch (uMsg)
 {
 
  case 1025: //WINSOCK message


   switch (lParam)
   {
    case FD_READ:

    if (wParam==FTPDATASOCK || wParam==REMOTEFTPCLIENTDATASOCK)
     {
      char *buffer=(char *) malloc(8192*sizeof(char));
      int recu=1;
      while (recu>0)
      { 
       ZeroMemory(buffer,8192);
       recu=recv(wParam,buffer,8192,0);
       if (HFTPDATAFILE!=NULL)
        fwrite(buffer,sizeof(char),recu,HFTPDATAFILE);
       Sleep(1000);
      }
      return 0;
     } 
   }
}

J'utilise des sockets non bloquantes (WSAAsyncSelect) et ceci est la procédure pour recopier un fichier transféré. En local je mets Sleep(50) pour maximiser la vitesse de transfert (200ko/s), mais si je mets cette valeur pour une utilisation sur internet alors les fichiers transférés auront une taille plus grosse qu'à l'origine. Et si je laisse Sleep(1000) alors le temps de téléchargement devient incroyablement long! Pour info, HFTPDATAFILE=fopen(filename,"wb");

Jattends vos conseils! Merci

2 réponses

thejojo1 Messages postés 13 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 28 août 2006
28 août 2006 à 18:40
Bon finalement jai trouvé. Comme quoi avec un peu d'acharnement on arrive à nos fins. Toutefois je ne vois pas pourquoi ca marche donc un peu d'éclaircissement serait le bienvenu;

      if (wParam= =FTPDATASOCK)// || wParam==REMOTEFTPCLIENTDATASOCK)
     {
      char *buffer=(char *) malloc(8192*sizeof(char)); 
      int recu=1;
      MSG msg;
      while (recu>0)
      { 
       ZeroMemory(buffer,8192);
       recu=recv(wParam,buffer,8192,0);
       if ((HFTPDATAFILE!=NULL) &(recu>0) )  //au cas ou les msg ont du retard la connexion est ptete deja fermée
        fwrite(buffer,sizeof(char),recu,HFTPDATAFILE);
       
       if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
       {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
       }
      }
      return 0;
     } 

Visiblement rajouté &(recu>0) convient. En fait fwrite devait écrire dans le fichier meme avec recu =0. C'est ca que je ne comprends pas bien. La gestion des messages apparait anecdotique mais au moins on ne bloque pas l'application.
Avec un peu de chance j'aurai aidé quelqu'un avec mon probleme!
0
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
28 août 2006 à 22:56
Salut,

Il y a pas mal de problemes dans ton code.

- Déja il manque le free(buffer), ce qui crée un gros mémory leak (8 Ko a chaque fd_read, pour un client ftp c'est énorme).

- Ensuite le PeekMessage() que tu as mis dans le deuxieme post n'est
pas utile, il va enlever un message de la pile 'aléatoirement'... Dans
le post précedent tu avais mis un Sleep(1000) mais tu te plaignais que
la vitesse de transfert etait lente: a quoi sert - il ?

- Enfin, je ne vois aucun traitement d'erreur dans ton code, ce qui me
semble indispensable pour un client ftp, car la fin du transfert sur
une connexion de transfert est marquée par la déconnection du
socket.  Il faut donc traiter systematiquement les erreurs qui se
trouvent dans HIWORD(lParam) 
lorsque tu recois FD_READ, ainsi que les erreurs que pourraient
retourner recv(). Il peut aussi arriver que lorsqu'on recoit un
FD_CLOSE, le buffer de reception du socket ne soit pas vide, auquel cas
on peut verifier s'il reste encore des données a lire avec
ioctlsocket(), puis faire un ou plusieurs recv() au besoin.
0
Rejoignez-nous