2014-06-11 3 views
0

J'utilise le code suivant pour envoyer un fichier via tcp.Problème d'envoi de fichier TCP dans .NET, Socket NetworkStream

Si j'envoie plusieurs fois le même fichier consécutivement pour tester s'il est robuste, je reçois le premier fichier correctement et l'autre foiré.

Tous les fichiers endommagés ont les mêmes octets incorrects et si je dors (un certain temps) tous les fichiers sont transférés correctement. J'ai remarqué que je devais instancier un nouveau tampon en lisant mon fichier pour que tout soit bien fait. Mais je ne comprends pas pourquoi.

Je crains que ma solution de réinstanciation d'un tampon ne puisse cacher un autre problème majeur. Toute suggestion?

using(var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) 
{ 
    using(var binaryReader = new BinaryReader(fileStream)) 
    { 
     var _sendingBuffer = new byte[BUFFER_SIZE]; 

     int length = (int)fileStream.Length; 
     int bytesRead = 0; 

     //Ensure we reached the end of the stream regardless of encoding 
     while (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length) 
     { 
      bytesRead = binaryReader.Read(_sendingBuffer, 0, _sendingBuffer.Length); 

      _socket.BeginSend(_sendingBuffer, 0, bytesRead, SocketFlags.None, SendFileCallback, null); 

      //without this i received some messed up data 
      _sendingBuffer = new byte[BUFFER_SIZE]; 
     }  
    } 
} 
+0

La partie d'envoi est mauvaise par la réponse. Peut-être que la partie de réception est cassée aussi bien. Postez le code. – usr

+0

Notez qu'il est plus facile de s'appuyer sur des protocoles standards comme HTTP. Les prises sont très difficiles à utiliser. – usr

+0

En fait, envoyer et recevoir des pièces fonctionnent, je ne cherche pas un moyen de faire ce travail. Je ne peux pas utiliser Http Je suis limité par mon environnement et les exigences et les politiques de nombreuses façons (WinCE) – sam

Répondre

2

BeginSend est une opération asynchrone. Il ne sera garanti que d'être lancé après l'avoir appelé, il ne sera pas terminé immédiatement. Tant que le socket envoie les données transmises, ces données ne doivent pas être mutées. La fin de l'opération sera signalée via le paramètre de rappel AsyncCallback.

Votre problème est précisément que vous avez muté le tampon de transmission alors que la transmission était encore en cours. Créer un nouveau tableau pour chaque appel de transmission corrige ceci.

D'autres façons de résoudre le problème:

  • Utilisez la fonction de blocage Socket.Send qui bloque jusqu'à ce que l'ensemble des données a été envoyé et peut être réutilisé le tampon. Cela rendra également votre traitement des erreurs beaucoup plus facile, car l'erreur n'apparaîtra pas à travers le AsyncCallback.
  • Exécutez votre programme complet de manière asynchrone, par ex. en utilisant C# 5 la tâche async et async/attendre les fonctionnalités Par conséquent:
    1. Première lecture une partie du fichier de manière asynchrone.
    2. Lorsque les finitions de lecture async envoient de manière asynchrone via la prise
    3. Lorsque cela se termine et il y a plus de données à lire revenir à 1.
+0

Je ne vois aucune documentation sur ce que vous dites sur le tampon. Je pense qu'il est possible que BeginSend copie les données de mon tampon localement et ensuite mettre en file d'attente ma demande. Avez-vous une référence? – sam

+0

Je peux obtenir tout en file d'attente AVANT que le premier rappel est appelé et le premier EndSend est appelé et tout est reçu correctement. Cela semble prouver ce que je dis – sam

+0

En outre, je fais face au problème sur le premier morceau la deuxième fois que ma méthode est appelée (seulement si je ne renouvelle pas le tampon). Puisque le tampon est méthode-local, je ne devrais pas non plus faire face à ce problème: c'est un nouveau tampon quand j'appelle la méthode. – sam