2009-09-20 17 views
11

Simplement j'ai essayé d'implémenter ce que BufferedStreamReader fait en Java. J'ai un flux de socket ouvert et je veux juste le lire de façon linéaire - ligne par ligne.C# - StreamReader.ReadLine ne fonctionne pas correctement!

J'ai le code serveur suivant.

while (continueProcess) 
     { 
      try 
      { 
       StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8); 
       string command = reader.ReadLine(); 
       if (command == null) 
        break; 

       OnClientExecute(command); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.ToString()); 
      } 
     } 

Et le client-code suivant:

TcpClient tcpClient = new TcpClient(); 
     try 
     { 
      tcpClient.Connect("localhost", serverPort); 
      StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8); 
      writer.AutoFlush = true; 
      writer.WriteLine("login>user,pass"); 
      writer.WriteLine("print>param1,param2,param3"); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
     finally 
     { 
      tcpClient.Close(); 
     } 

Le serveur ne lit que la première ligne (login>user,pass) puis ReadLine retourne NULL!

Quelle est la manière la plus simple de réaliser ce lecteur orienté ligne comme dans Java BufferedStreamReader? : s

+1

S'il vous plaît, jetez vos objets ici (StreamReader et StreamWriter). Sinon, vous risquez d'avoir des problèmes inattendus. Il suffit de mettre un bloc d'utilisation autour d'eux (comme en utilisant (écrivain StreamWriter = ...) {}), et vous serez ok – configurator

+0

Pas que c'était pertinent à la question - juste une suggestion. – configurator

+0

génial;) grâce – Aleyna

Répondre

12

Une ligne lecteur typique est quelque chose comme:

using(StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) { 
    string line; 
    while((line = reader.ReadLine()) != null) { 
     // do something with line 
    } 
} 

(notez le using pour nous assurer Dispose() même si nous obtenons une erreur, et la boucle)

Si vous voulez, vous pourriez abstraite cette (séparation des préoccupations) avec un bloc itérateur:

static IEnumerable<string> ReadLines(Stream source, Encoding encoding) { 
    using(StreamReader reader = new StreamReader(source, encoding)) { 
     string line; 
     while((line = reader.ReadLine()) != null) { 
      yield return line; 
     } 
    } 
} 

(noter que nous avons déplacé cela en fonction et a retiré le « faire quelque chose », vidange dan ng avec « retour de rendement », ce qui crée un iterator (un paresseusement itéré, machine d'état non-tampon)

Nous pourrions alors consommer ce aussi simple que:

foreach(string line in ReadLines(Socket.GetStream(), Encoding.UTF8)) { 
    // do something with line 
} 

Maintenant, notre code de traitement ne pas besoin de s'inquiéter comment pour lire les lignes - simplement donné une séquence de lignes, faire quelque chose avec eux. Notez que le using (Dispose()) s'applique également à TcpClient; vous devriez prendre l'habitude de vérifier IDisposable; par exemple (y compris encore votre diagraphie d'erreur):

using(TcpClient tcpClient = new TcpClient()) { 
    try { 
     tcpClient.Connect("localhost", serverPort); 
     StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8); 
     writer.AutoFlush = true; 
     writer.WriteLine("login>user,pass"); 
     writer.WriteLine("print>param1,param2,param3"); 
    } catch (Exception ex) { 
     Console.Error.WriteLine(ex.ToString()); 
    } 
} 
+0

Lorsque j'utilise StreamReader pour lire à partir du socket, j'ai constaté que le programme client gèle, prend une quantité infinie de temps à la méthode ReadLine(), et finalement ne parvient pas à lire. –

+0

@MasudRahman qui signifie généralement soit: le serveur n'envoie pas une ligne complète (c'est-à-dire que vous lui demandez d'attendre quelque chose que le serveur n'a pas de raison de vous envoyer), soit le serveur a oublié de tampon de sortie. Vous pouvez * ajouter * un délai de lecture, mais en fin de compte, il ne peut pas envoyer des données au serveur. Vous pouvez bien sûr faire la lecture et la mise en mémoire tampon, mais cela ne fait que changer la nature du problème - il peut alors être votre travail de décider qu'une ligne complète n'a pas été envoyée après un certain temps. –

5

Le temps de votre code serveur est configuré pour lire uniquement une ligne par connexion. Vous aurez besoin d'un autre moment pour essayer de lire toutes les lignes envoyées. Je pense qu'une fois que ce flux est configuré du côté client, il va envoyer toutes les données. Ensuite, du côté serveur, votre flux ne lit en réalité qu'une seule ligne de ce flux particulier.

+0

Après avoir modifié mon serveur et le code client comme suit serveur: à l'aide (lecteur StreamReader = new StreamReader (Socket.GetStream(), Encoding.UTF8)) { while (continueProcess) .... client : ... Thread.Sleep (10000); writer.WriteLine ("print> test, one, two"); J'ai inséré Thread.Sleep (10000) dans mon code client et le serveur a lancé une exception de lancement. Le socket client sera ouvert jusqu'à ce que le client quitte et puisque le client enverra des données tout au long de son cycle de vie semble que ce code va générer des erreurs. Tu ne le crois pas? – Aleyna

+0

Sans voir ce que le nouveau code ou la nouvelle exception est, je ne suis pas sûr de ce que le problème pourrait être. – LJM

0

essayé et obtenu

Le type ou le nom namespace Stream 'n'a pas pu être trouvé (vous manque une directive à l'aide ou une référence d'assemblage? Le type ou le nom d'espace de noms 'StreamReader' est introuvable (une directive using ou une référence d'assembly est-elle manquante?) Le nom de type ou d'espace de noms 'StreamReader' est introuvable (une directive using ou un assembly référence?) 'System.Net.Sockets.Socket' ne contient pas de définition pour 'GetStream'

+1

pls se référer à http://msdn.microsoft.com/en-us/library/system.io.stream.aspx – Aleyna

0
public string READS() 
    { 
     byte[] buf = new byte[CLI.Available];//set buffer 
     CLI.Receive(buf);//read bytes from stream 
     string line = UTF8Encoding.UTF8.GetString(buf);//get string from bytes 
     return line;//return string from bytes 
    } 
    public void WRITES(string text) 
    { 
     byte[] buf = UTF8Encoding.UTF8.GetBytes(text);//get bytes of text 
     CLI.Send(buf);//send bytes 
    } 

CLI est une socket. pour certains rezoner la classe TcpClient ne fonctionne plus sur mon PC, mais la classe Socket fonctionne très bien.

UTF-8 est le StreamReader/Writer brin d'encodage

Questions connexes