2010-08-24 4 views
1
var buffer = new byte[short.MaxValue]; 
var splitString = new string[] {"\r\n"}; 
while (_tcpClient.Connected) 
{ 
    if (!_networkStream.CanRead || !_networkStream.DataAvailable) 
    continue; 

    var bytesRead = _networkStream.Read(buffer, 0, buffer.Length); 
    var stringBuffer = Encoding.ASCII.GetString(buffer, 0, bytesRead); 
    var messages = 
    stringBuffer.Split(splitString, StringSplitOptions.RemoveEmptyEntries); 
    foreach (var message in messages) 
    { 
    if (MessageReceived != null) 
    { 
     MessageReceived(this, new SimpleTextClientEventArgs(message)); 
    } 
    } 
} 

Le problème est que même avec un tampon aussi grand que court. MaxValeur, vous pouvez réellement remplir le tampon. Lorsque vous séparez la chaîne que vous créez à partir du tampon, la dernière chaîne est tronquée, et le reste vient avec la lecture suivante. Je pensais créer un buffer assez grand pour une seule ligne (ce qui selon la RFC2812 est de 512 caractères), extraire une sous-chaîne jusqu'au premier "\ r \ n", puis copier en tableau le reste des données au début du tampon et en utilisant le paramètre offset pour lire plus de données sur la fin de la donnée qui n'a pas été extraite la dernière itération. Désolé si c'était difficile à suivre ...IRC utilisant NetworkStream - le tampon se remplit et la ligne est tronquée

Est-ce la meilleure solution, ou est-ce que je manque l'évidence ici?

+0

êtes-vous sûr que le tampon est plein, pas que 'bytesRead' n'est pas la même taille que le nombre d'octets envoyés? –

+0

Cela pourrait être le cas - mais ce n'est généralement pas le cas. – carlsb3rg

Répondre

0

Alors, voici comment je fini par résoudre:

var buffer = new byte[Resources.MaxBufferSize]; 
var contentLength = 0; 
while (_tcpClient.Connected) 
{ 
    if (!_networkStream.CanRead || !_networkStream.DataAvailable) 
    continue; 

    var bytesRead = _networkStream.Read(buffer, contentLength, buffer.Length - contentLength - 1); 
    contentLength += bytesRead; 
    var message = string.Empty; 
    do 
    { 
    message = ExtractMessage(ref buffer, ref contentLength); 
    if (!String.IsNullOrEmpty(message)) 
    { 
     if (MessageReceived != null) 
     { 
     MessageReceived(this, new SimpleTextClientEventArgs(message)); 
     }       
    } 
    } while (message != string.Empty); 
} 

private string ExtractMessage(ref byte[] buffer, ref int length) 
{ 
    var message = string.Empty; 
    var stringBuffer = Encoding.UTF8.GetString(buffer, 0, length); 
    var lineBreakPosition = stringBuffer.IndexOf(Resources.LineBreak); 
    if (lineBreakPosition > -1) 
    { 
    message = stringBuffer.Substring(0, lineBreakPosition); 
    var tempBuffer = new byte[Resources.MaxBufferSize]; 
    length = length - message.Length - Resources.LineBreak.Length; 
    if (length > 0) 
    { 
     Array.Copy(buffer, lineBreakPosition + Resources.LineBreak.Length, tempBuffer, 0, length); 
     buffer = tempBuffer; 
    } 
    } 
    return message; 
} 
1

Vous avez affaire à TCP/IP, ce qui signifie que vous avez affaire à flux données. Vous devez pas compter sur la façon dont les données viennent en termes de savoir si un appel à Read vous donnera l'ensemble des données ou non. Dans un cas comme celui-ci, vous voudrez probablement continuer à lire (il bloquera jusqu'à ce qu'il y ait des données) et trouver convertir les données binaires dans un tampon de texte. Lorsque vous voyez un terminateur de ligne dans le tampon de texte, vous pouvez notifier le niveau supérieur de ce message, et le retirer du tampon ... mais n'assumez rien sur ce qui vient après ce message. Vous pouvez toujours avoir plus de données à lire.

En note, IRC est vraiment seulement ASCII? Si oui, au moins rend les choses un peu plus simple ...

+0

-Ceci est ce qu'il dit: - "Aucun jeu de caractères spécifique n'est spécifié.Le protocole est basé sur un ensemble de codes composé de huit (8) bits, constituant un octet.Chaque message peut être composé de n'importe quel nombre de ces octets, cependant, certaines valeurs d'octet sont utilisées pour les codes de contrôle, qui agissent comme des délimiteurs de message. " -Mais je sais qu'il y a eu des améliorations non documentées/non documentées du protocole IRC, alors je voudrais rendre les choses aussi robustes que possible. Je pense que votre suggestion est ce que je suggère dans mon dernier paragraphe. – carlsb3rg

+0

@ carlsb3rg: Oui, il semble que vous pensiez peut-être dans le même sens que moi. Il semble que le protocole soit complètement cassé s'il ne spécifie pas un encodage ... et en supposant que l'ASCII pourrait facilement perdre des données importantes. En particulier, il semble que vous devriez regarder à travers le tableau d'octets pour le délimiteur de message plutôt que le texte décodé. –

Questions connexes