TcpClient.GetStream().DataAvailable retourne false, mais stream a plus de données
Donc, il semblerait qu'un blocage de la Lecture() peut retourner avant qu'il se fait de recevoir toutes les données qui lui sont envoyées. Nous envelopper le Lire() avec une boucle qui est contrôlé par la valeur DataAvailable à partir du flux en question. Le problème, c'est que vous pouvez recevoir plus de données, tandis que dans cette boucle, mais il n'y a pas de derrière les coulisses de traitement de passe pour laisser le système le savoir. La plupart des solutions que j'ai trouvé ça sur le net n'ont pas été d'une façon ou d'une autre pour moi.
Ce que j'ai fini par faire, c'est comme la dernière étape dans ma boucle, je fais un simple Fil.Sleep(1) après la lecture de chaque pâté de maisons de la rivière. Cela semble donner au système le temps de mettre à jour et je ne suis pas d'obtenir des résultats précis, mais cela semble un peu hacky et tout à fait un peu "circonstancielle" pour une solution.
Voici une liste de ces circonstances, je fais affaire avec: une Seule Connexion TCP entre une Application IIS et une application autonome, tant à l'écrit en C# pour envoyer/recevoir des communications. Il envoie une requête et attend une réponse. Cette demande est initiée par une requête HTTP, mais je ne suis pas avoir ce problème de la lecture des données de la Requête HTTP, il est après le fait.
Voici le code de base pour la manipulation d'une connexion entrante
protected void OnClientCommunication(TcpClient oClient)
{
NetworkStream stream = oClient.GetStream();
MemoryStream msIn = new MemoryStream();
byte[] aMessage = new byte[4096];
int iBytesRead = 0;
while ( stream.DataAvailable )
{
int iRead = stream.Read(aMessage, 0, aMessage.Length);
iBytesRead += iRead;
msIn.Write(aMessage, 0, iRead);
Thread.Sleep(1);
}
MemoryStream msOut = new MemoryStream();
//.. Do some processing adding data to the msOut stream
msOut.WriteTo(stream);
stream.Flush();
oClient.Close();
}
Tous les commentaires de bienvenue pour une meilleure solution ou juste un coup de pouce sur le besoin de donner que de Sommeil(1) allez à laisser les choses se mettre à jour correctement avant de nous vérifions la valeur DataAvailable.
Suppose que je suis l'espoir au bout de 2 ans que la réponse à cette question n'est pas la façon dont les choses sont encore 🙂
Oui, c'est juste la façon dont ces bibliothèques travail. Ils ont besoin d'avoir de temps à s'exécuter pour valider entièrement les données entrantes.
OriginalL'auteur James | 2010-11-23
Vous devez vous connecter pour publier un commentaire.
Je vois un problème avec ce.
Vous attendez que la communication sera plus rapide que l'
while()
boucle, ce qui est très peu probable.Le
while()
boucle sera fini dès qu'il n'y a pas plus de données, ce qui peut ne pas être le cas de quelques millisecondes seulement après sa sortie.Vous attendez-vous à une certaine quantité d'octets?
Quelle est la fréquence de
OnClientCommunication()
tiré? Qui la déclenche?Que faire avec les données après la
while()
boucle? Gardez-vous d'ajouter un jeu de données précédentes?DataAvailable
SERA return false parce que vous êtes en train de lire plus vite que la communication, c'est très bien que si vous garder de revenir à ce bloc de code à traiter plus de données.Bon, sa fait un an et 1000 vues sans mises à jour, donc je vais juste accepter que c'est la réponse.
ce n'est pas une bonne raison pour accepter la réponse et c'est un peu tromper d'autres qui ont besoin/l'utilisation de cette information.
Désolé, mais la réponse est vraiment que c'est juste la façon dont les choses sont. Vous avez besoin de dormir() dans la boucle while pour le tampon de données pour pouvoir être rempli comme indiqué dans la question d'origine. Si cela ne change jamais alors un nouvel élément de réponse peut être sélectionné mais c'est comme ça pour l'instant.
OriginalL'auteur BeemerGuy
Vous devez savoir combien de données vous avez besoin de lire; vous ne pouvez pas tout simplement de la boucle de lecture des données jusqu'à ce qu'il n'y a plus de données, parce que vous ne pouvez jamais être sûr qu'aucun autre va venir.
C'est pourquoi HTTP OBTENIR des résultats ont un nombre d'octets dans les en-têtes HTTP: de sorte que le côté client permettra de savoir quand il a reçu toutes les données.
Voici deux solutions pour vous en fonction de si vous avez le contrôle sur ce que l'autre côté est de l'envoi:
Utilisation de "cadrage" des personnages: (SB)de données(EB), où SB et EB sont bloc de début et de fin de bloc de caractères (de votre choix), mais qui NE peut pas se produire à l'intérieur des données. Lorsque vous "voir" EB, vous savez que vous êtes fait.
Mettre en œuvre un champ de longueur à l'avant de chaque message pour indiquer la quantité de données qui suit: (len)de données. Lire (len), la lecture (len) octets; répétez l'opération si nécessaire.
Ce n'est pas comme la lecture à partir d'un fichier de longueur nulle lire signifie en fin de données (cela signifie que de l'autre côté s'est déconnecté, mais c'est une autre histoire).
Un tiers (non recommandé) de la solution est que vous pouvez mettre en œuvre une minuterie. Une fois vous commencez à recevoir des données, de régler la minuterie. Si la boucle de réception est inactif pendant une certaine période de temps (disons quelques secondes, si les données ne viennent pas souvent), vous pouvez sans doute supposer que plus de données sont à venir. Cette dernière méthode est le dernier recours... il n'est pas très fiable, difficile à ajuster, et c'est fragile.
OriginalL'auteur Larry
J'ai essayé de vérifier DataAvailable avant de lire des données à partir d'un flux réseau et il serait de retour faux, même si, après la lecture d'un seul octet, il serait de retour vrai. Donc j'ai vérifié la documentation MSDN et ils ont également lire avant de vérifier. Je re-arranger le tout en boucle une boucle do while à suivre ce modèle.
http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.dataavailable.aspx
OriginalL'auteur Despertar
Quand j'ai ce code:
De ce que je peux observer:
Quand j'ai ce code:
Puis le NetworkStream avoir assez de temps pour régler correctement .DataAvailable et cette méthode devrait fonctionner correctement.
Fait amusant... Ce qui semble être en quelque sorte OS dépendant de la Version. Parce que la première fonction sans sommeil a fonctionné pour moi sur Win XP et Win 10, mais a échoué à recevoir l'ensemble 1000 octets sur Win 7. Ne me demandez pas pourquoi, mais je l'ai testé tout à fait à fond et il est facilement reproductible.
OriginalL'auteur Jacob