2014-09-03 2 views
0

J'ai deux logiciels, l'un étant un serveur et l'autre étant l'interface client.L'écriture NetworkStream ne se termine pas si le thread n'est pas dormi

Dans mon serveur, je prends et demande la manipulation puis retourner une chaîne par une méthode que j'ai écrit « réponse »

public static void reply(string buffer, NetworkStream stream) 
    { 
     stream.Write(Encoding.ASCII.GetBytes(buffer), 0, buffer.Length); 
    } 

la question que j'ai est que par exemple, si je devais faire le code ci-dessous

for(int i = 0; i<5; i++){ 
reply("SOME REPLY", stream); 
} 

le code ci-dessus écrire des lignes newlined aléatoires au client comme ceci:

SOME REPLY 
SOME REPLYSOME REPLY 
SOME REPLY 
SOME REPLYSOME REPLYSOME REPLY 
SOME REPLYSOME REPLY 
SOME REPLY 
SOME REPLY 

Si je devais mettre un appel Thread.Sleep 200ms dans le forloop, il aurait correctement souligné les réponses. Du côté client le code ci-dessous comment nous lisons à partir du serveur et de l'impression à la console:

 Byte[] bytes = new Byte[256]; 
     NetworkStream stream = endpoint.GetStream(); 
     int i; 
     while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
     { 
      Console.WriteLine(System.Text.Encoding.ASCII.GetString(bytes, 0, i)); 
     } 

Répondre

2

Votre problème est que le client n'envoie un saut de ligne, de sorte que le serveur n'a pratiquement pas la moindre idée où mettre les nouvelles lignes. Le fait que vous obteniez «quelques» retours à la ligne, est lié à la façon dont le flux est utilisé, un NetworkStream lira toujours toutes les données disponibles lorsque vous appelez read, ou attendez que -some- data soit disponible; il n'y a aucune garantie que ce que vous recevez est ce que vous voulez. Vous pouvez lire toutes les données d'un flux côté serveur dans votre application, puis ajouter une nouvelle ligne (à cause de l'appel Console.WriteLine), puis continuer pour lire la partie suivante du message.

Je suppose que la meilleure façon de contourner cela est de changer simplement l'appel reply("SOME REPLY", stream); à reply("SOME REPLY" + Environment.NewLine, stream); puis modifiez l'appel Console.WriteLine sur le côté serveur à un simple appel Console.Write. Une meilleure façon, mais un peu plus complexe, de gérer les messages fragmentés ou tamponnés consisterait à toujours envoyer un "byte-count" devant votre message du côté client, afin que le serveur sache combien d'octets lire avant l'ajout d'une nouvelle ligne:

pseudocode:

Client => Send([number of bytes] + [data]) 
Server => Read([number of bytes] (Field)) 
Server => Read([data]) until received bytes count == [number of bytes] 
+0

C'est ici qu'utiliser un ['BinaryWriter'] (http://msdn.microsoft.com/fr-fr/library/yzxa6408 (v = vs.110) .aspx) peut être utile. Il fait l'écriture des octets de longueur principaux pour vous. –

+0

Merci, j'ai effectivement essayé de faire "\ n" sans succès mais je ne crois pas que je suis passé à l'utilisation de "writ" sur "writeline". Votre fixe a bien fonctionné. – user2887749

+0

Si vous êtes sur Windows, \ n vous aurez besoin de \ n \ n - en particulier dans .NET - Voir la propriété Environment.NewLine. – t0yk4t

1

le serveur n'écrit aucun retour à la ligne du tout au client, il est le client qui insère des sauts de ligne après chaque bloc de texte qu'il lit.

Lorsque quelque chose survient sur le flux réseau, le client lira tout ce qui est actuellement dans le tampon et écrira une nouvelle ligne après cela. Lors du traitement de cette partie des données, le serveur a peut-être eu le temps d'écrire plusieurs morceaux de texte dans le flux. Ainsi, la prochaine fois que le client lit le flux, il peut obtenir plus d'un texte à la fois. La seule chose qui sépare les morceaux de texte provenant du serveur est un petit intervalle de temps, et le client ne l'a pas remarqué car il était occupé à traiter ce qu'il avait lu avant cela. Vous pouvez essayer de faire en sorte que le code prenne en compte ces décalages horaires, mais c'est loin d'être une solution robuste.

Si vous souhaitez séparer les parties de texte, vous devez envoyer quelque chose dans le flux réel que le client peut ramasser de manière fiable. Si vous voulez simplement un saut de ligne entre le texte, envoyez les sauts de ligne au serveur, puis le client peut simplement écrire ce qu'il obtient sans y ajouter quoi que ce soit.