2017-04-24 4 views
1

Je reçois un flux dont la longueur varie mais qui présente un caractère de début et de fin. Lorsque j'exécute ce code:Longueur de l'octet de la variable d'écoute TCP/IP

public TCPListener() 
{ 
     Int32 port = 31001; 
     IPAddress localAddr = IPAddress.Parse("192.168.0.78"); //Local 
     server = new TcpListener(localAddr, port); 
     server.Start(); 

     while (true) 
     { 
      // Console.Write("Waiting for a connection...-- "); 
      TcpClient client = server.AcceptTcpClient(); 

      // Console.WriteLine("new client connected"); 
      try 
      { 
       ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client); 
      } 
      catch (Exception ex) 
      { } 
     } 
    } 

    private void HandleClient(object tcpClient) 
    { 
     // string path = @"c:\Test.txt"; 
     TcpClient client = (TcpClient)tcpClient; 
     Byte[] bytes = new Byte[135]; 
     String data = null; 
     int i; 

     try 
     { 
      NetworkStream stream = client.GetStream(); 

      while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
      { 
       data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); 
       URLObject oU = new URLObject(); 
       oU = oDecode.TextFrameDecode(data); 
       Console.WriteLine(data); 
       Console.WriteLine(""); 
      } 
     } 
     catch (Exception ex) 
     { } 

     // Console.WriteLine(data); 
} 

Je reçois beaucoup de données chaque seconde; Je reçois les données, mais elles sont parfois fragmentées en morceaux qui ne sont pas analysables. Lorsque j'exécute ce code pour rechercher le délimiteur de fin, le flux n'obtient qu'une connexion toutes les deux minutes avec un seul enregistrement, donc je pense que les données sont tronquées, ce qui n'est pas correct.

static void Main(string[] args) 
{ 
     Int32 port = 31001; 
     IPAddress localAddr = IPAddress.Parse("192.168.0.78"); //Local 
     server = new TcpListener(localAddr, port); 
     server.Start(); 

     while (true) 
     { 
      Console.Write("Waiting for a connection...-- "); 
      TcpClient client = server.AcceptTcpClient(); 
      Console.WriteLine("new client connected"); 

      try 
      { 
       ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client); 
      } 
      catch (Exception ex) 
      { } 
     } 
} 

static void HandleClient(object tcpClient) 
{ 
     TcpClient client = (TcpClient)tcpClient; 
     Byte[] bytes = new Byte[135]; 
     String data = null; 
     int i; 

     try 
     { 
      using (NetworkStream stream = client.GetStream()) 
      using (StreamReader reader = new StreamReader(stream)) 
      { 
       string inputLine = reader.ReadLineSingleBreak(); 
       inputLine = inputLine + "#"; 
       Console.WriteLine(inputLine); 
       URLObject oU = new URLObject(); 
       oU = oDecode.TextFrameDecode(inputLine); 
      } 
     } 
     catch (Exception ex) 
     { } 
    } 
} 

public static class StreamReaderExtensions 
{ 
    public static string ReadLineSingleBreak(this StreamReader self) 
    { 
     StringBuilder currentLine = new StringBuilder(); 
     int i; 
     char c; 

     while ((i = self.Read()) >= 0) 
     { 
      c = (char)i; 

      if (c == '#') 
      { 
       break; 
      } 

      currentLine.Append(c); 
     } 

     return currentLine.ToString(); 
    } 
} 

J'ai besoin d'un mélange des deux ... obtenir toutes les données, mais ensuite analyser correctement.

+2

vous ne devriez pas autant que je sache supposer que chaque appel 'read' lit un message complet. Je commencerais par modifier cette boucle 'stream.Read': ajouter les résultats de chaque appel' Read' à un tampon, et seulement analyser ce tampon lorsque le dernier appel 'Read' contenait un caractère d'arrêt. –

+1

Votre méthode 'HandleClient' dans le second exemple n'a pas de boucle. Il ne peut pas traiter plus d'un seul enregistrement, puisqu'il se termine simplement * après le premier. Le premier exemple suppose qu'un seul 'Write 'du côté de l'envoi provoque un seul' Read' du côté de la réception - ce qui n'est tout simplement pas vrai pour TCP. TCP est un protocole basé sur les flux, il n'a pas de "messages" - donc le lire comme un flux. Un seul 'Read' peut recevoir moins d'un de vos messages, ou plusieurs d'entre eux en même temps. Soyez prêt pour ça. – Luaan

+0

vous pouvez grandement simplifier l'implémentation si au lieu d'utiliser le délimiteur vous préfixez vos données par sa taille, bien sûr si vous pouvez modifier votre protocole, par ex. pour envoyer "certaines données" chaîne vous envoyez réellement "[9] certaines données" où "[9]" est 4 octets int avec la valeur "9" sous forme binaire –

Répondre

0

j'ai fait réparer par des conseils Pieter Witvoet:

static private TcpListener server = null; 
    static private Decode oDecode = new Decode(); 
    static private string sLeftOver = string.Empty; 
    static void Main(string[] args) 
    { 
     Int32 port = 31001; 
     IPAddress localAddr = IPAddress.Parse("192.168.0.78"); //Local 
     server = new TcpListener(localAddr, port); 
     server.Start(); 
     while (true) 
     { 
      Console.Write("Waiting for a connection...-- "); 
      TcpClient client = server.AcceptTcpClient(); 
      Console.WriteLine("new client connected"); 
      try 
      { 
       ThreadPool.QueueUserWorkItem(new WaitCallback(HandleClient), client); 
      } 
      catch (Exception ex) 
      { } 
     } 
    } 
    static void HandleClient(object tcpClient) 
    { 
     TcpClient client = (TcpClient)tcpClient; 
     Byte[] bytes = new Byte[256]; 
     String data = null; 
     int i; 
     try 
     { 
      NetworkStream stream = client.GetStream(); 
      while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
      { 
       data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); 
       URLObject oU = new URLObject(); 

       Console.WriteLine(data); 
       Console.WriteLine(""); 
       //Split data here 
       string[] aData = Regex.Split(data, @"(?<=[#])"); 
       foreach (string s in aData) 
       { 
        string sData = s; 
        sData = sLeftOver + sData; 
        if (sData.EndsWith("#")) 
        { 
         sLeftOver = string.Empty; 
         Console.WriteLine(sData); 
         Console.WriteLine(""); 
         oU = oDecode.TextFrameDecode(sData); 
               } 
        else 
        { 
         sLeftOver = s; 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { } 
    }