2012-03-02 2 views
1

J'ai une application client qui envoie un fichier au serveur. Le problème est que dans la partie client, le fichier est lu correctement, je peux enregistrer à nouveau le tableau d'octets après l'avoir lu et il l'enregistre en tant que jpg valide. Sur le serveur, cependant, les données sont corrompues à certains endroits. Tout ce que je fais est de continuer à ajouter à la liste toutes les données entrantes jusqu'à ce que le client ferme la connexion.Client TCP - Les données ne sont corrompues que dans certaines parties

Je chevauchaient les données client et serveur envoyés/reçus et que vous pouvez le voir, il y a des endroits où les données ne correspondent pas: http://s16.postimage.org/mtmm1hssl/corrupted_data.png

Je ne comprends pas comment est-ce possible, j'utilise un grand tampon et l'image est assez petite, donc même lorsque l'image est reçue par le serveur dans un morceau, les données sont toujours corrompues.

Des idées pour lesquelles cela se passe?

MISE À JOUR:

côté client:

Je suis aller chercher une image HttpWebRequest:

    List<byte> test_buffer = new List<byte>(); 

        using (Stream MyResponseStream = hwresponse.GetResponseStream()) 
        { 
         byte[] MyBuffer = new byte[4096]; 
         int BytesRead; 

         while (0 < (BytesRead = MyResponseStream.Read(MyBuffer, 0, MyBuffer.Length))) 
         { 

          for (int i = 0; i < BytesRead; i++) 
          { 
           test_buffer.Add(MyBuffer[i]); // just for testing 
          } 

          TCP_R.SendBytes(MyBuffer); // send data back to server 
         } 
        } 

        TCP_R.Close(); // tell server that we're done sending data 

TCP_R est une classe qui gère tous les trucs TCP (se connecter à serveur/envoyer des données)

Ceci est la fonction TCP_R.SendBytes:

public void SendBytes(Byte[] data) 
    { 
     try 
     { 
      if (m_clientSocket != null) 
      { 
       m_clientSocket.Send(data); 
      } 

     } 
     catch (SocketException se) 
     { 
      log("send_bytes err: " + se.Message); 
     } 
    } 

Avis J'utilisé test_buffer pour recueillir tous les octets afin de vérifier si tout est bien reçu. Si j'utilise ce code:

    MemoryStream ms = new MemoryStream(test_buffer.ToArray()); 
        Image returnImage = Image.FromStream(ms); 
        returnImage.Save("image.jpg"); 

L'image a été créée avec succès. Donc, je suppose que le client envoie des données correctement.

côté serveur:

I recueillir les données en utilisant la fonction OnDataReceived et de construire toutes les données REQUEST_RESPONSE qui est List<byte>:

public void OnDataReceived(IAsyncResult asyn) 
    { 

     try 
     { 
      SocketPacket socketData = (SocketPacket)asyn.AsyncState; // cast 

      int iRx = 0; 

       iRx = socketData.m_currentSocket.EndReceive(asyn); 
       char[] chars = new char[iRx + 1]; 

       System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder(); // CAN THIS BE CAUSING THE PROBLEM!?! 
       int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0); 


       for (int s = 0; s < charLen; s++) 
       { 

        RESPONSE_DATA.Add(socketData.dataBuffer[s]); // Collect response data 

       } 

       WaitForData(socketData.m_currentSocket, socketData.socket_id, REQUEST_INDEX_ID); 

      } 

     } 
     catch (ObjectDisposedException) 
     { 

     } 
     catch (SocketException se) 
     { 

     } 
    } 

MAJ2: Il semble que ces lignes sont à l'origine le problème:

   System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder(); // CAN THIS BE CAUSING THE PROBLEM!?! 
       int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0); 

Comment puis-je récupérer les données dans socketData.dataBuffer sans utiliser Decoder?

SOLUTION:. Même si je lisais directement à partir DataBuffer, les « Les d.GetChars (socketData.dataBuffer .. » ligne en quelque sorte vissé le tampon et celui-ci je me suis vissé des données j'ai encore besoin d'utiliser GetChars trop pour lire la première partie du paquet sous forme de chaîne, donc je simplement changé:

int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0); 

à:

byte[] tmp_a = new byte[socketData.dataBuffer.Length]; 
tmp_a = socketData.dataBuffer; 
int charLen = d.GetChars(tmp_a, 0, iRx, chars, 0); 

Et maintenant, tout fonctionne bien.Apparemment, l'appel de getChars directement sur le tampon affectait le tampon.

+0

Montrez-nous du code. Vous ne pouvez pas attendre que nous répondions à cette question si vous omettez tous les détails. – usr

+0

Je soupçonne que quelque chose ne va pas dans votre code, que ce soit sur le client ou sur le serveur. Malheureusement, vous ne nous avez pas montré le code du client ou du serveur, ce qui le rend difficile à dire ... –

+0

Besoin de voir votre code ... à la fois l'envoi et la réception. –

Répondre

2

Cela ressemble à un problème d'encodage.

Le concept clé ici est que l'encodage est pour le texte, et les images ne sont pas du texte. N'essayez pas de coder ou de décoder les octets avant l'envoi ou après la réception. De même, si vous lisez ou écrivez l'image depuis ou vers un fichier, n'essayez pas de coder ou de décoder, utilisez un mode binaire.

N'essayez simplement pas de convertir les octets en caractères, il n'y a aucun moyen significatif de le faire.

+0

C'est de la pure spéculation. En particulier, l'envoi brut de données binaires sur tcp ne devrait impliquer aucun encodage. –

+0

La question ne se prête pas à autre chose qu'à la spéculation. –

+0

Et oui, cela ne devrait impliquer aucun encodage, c'est pourquoi je pensais que l'encodage pourrait être le problème. –

Questions connexes