2017-09-21 9 views
-1

Ich habe eine Server-Anwendung, bekomme aber einige zeitweilige Timeouts. Ich möchte sofort mit dem Schreiben auf den Client beginnen und dann den Rest meines Schreibvorgangs verschieben, bis meine Nutzlast bereit ist. Nichts, was ich in TcpClient oder NetworkStream gesehen habe, unterstützt jedoch aktives Streaming. In meinem eigenen Testbett ist jeder Schreibvorgang für den Stream isoliert, sogar die Anfangs-/Ende-Methode.Socket Constant Streaming-Daten

Zum Beispiel, in meiner Client-Seite Schreib/Lese-Schleife, sendet der folgende Server-Code nur eine einmalige Eingabe statt zwei zurück.

static void Main(string[] args) 
    { 
     var listener = TcpListener.Create(2345); 

     listener.Start(); 

     while (true) 
     { 
      var client = listener.AcceptTcpClientAsync().Result; 

      ThreadPool.QueueUserWorkItem(async state => 
      { 
       try 
       { 
        await HandleClient(state); 
       } 
       catch (SocketException error) when (error.Message.Contains("existing connection was forcibly closed")) 
       { 
        // do nothing 
       } 
      }, client); 
     } 
    } 

    private static async Task HandleClient(object state) 
    { 
     var client = (TcpClient) state; 
     var stream = client.GetStream(); 

     while (true) 
     { 
      var readBuffer = new byte[4096]; 

      var requestSize = await stream.ReadAsync(readBuffer, 0, readBuffer.Length); 

      var requestString = Encoding.ASCII.GetString(readBuffer, 0, requestSize); 

      Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] Received: {requestString}"); 

      if (requestString == "quit") 
      { 
       break; 
      } 

      var responseString = DateTime.Now.ToLongTimeString(); 

      var writeBuffer = Encoding.ASCII.GetBytes(responseString); 

      stream.BeginWrite(writeBuffer, 0, writeBuffer.Length, DelayedWriteCallback, stream); 
     } 

     client.Close(); 
     client.Dispose(); 
    } 

    private static void DelayedWriteCallback(IAsyncResult ar) 
    { 
     var stream = (NetworkStream) ar.AsyncState; 

     Thread.Sleep(5000); 

     var writeString = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString()); 

     stream.Write(writeString, 0, writeString.Length); 
     stream.Flush(); 

     stream.EndWrite(ar); 
    } 

Wie mache ich das?

+0

Sie rufen ein anderes BeginWrite in Ihrem DelayedWriteCallback nach dem EndWrite auf und fügen Logik hinzu, um das Senden zu beenden. Wahrscheinlich einfacher zu Aufgaben zu verwenden, vermeiden Sie den Rückruf-Aufwand. –

+0

Leider funktioniert das nicht. Auf der Clientseite ist das Lesen abgeschlossen, und die zusätzlichen Schreibvorgänge auf dem Serverende werden erst zurückgegeben, wenn weitere Lesevorgänge ausgeführt werden. Ich möchte, dass der Client an dem gleichen Lesevorgang hängt, bis ich mit dem Schreiben fertig bin, so dass alles wie eine Anfrage/Antwort an den Client aussieht. – Bigsby

+0

Sie verwenden dieselbe Logik auf beiden Seiten (wobei die Sockets für die Dauer beibehalten werden), wobei die Logik erkennt, wann das Ganze beendet ist. Sockets werden Bytes nur so lange mischen, wie Sie möchten. Die Bedeutung der Daten hängt von Ihren Apps ab. –

Antwort

0

TCP ist ein Streaming-Protokoll, was bedeutet, dass es alle von Ihnen gesendeten Daten transportiert und sicherstellt, dass sie auf der anderen Seite in der richtigen Reihenfolge empfangen werden.

Diese Daten könnten eine konstante Folge von Bytes sein, oder viele Sekunden von nichts gefolgt von einem einzelnen Byte. TCP ist es egal, es ist nur die Pfeife für.

Dies wird durch die Tatsache verdeutlicht, dass jede Socket-Methode zum Senden und Empfangen einen Puffer mit einer bestimmten Größe als Parameter verwendet (dasselbe gilt für NetworkStream). Das "Streamen" von Nutzdaten obliegt der Anwendung, ebenso der Empfang und die Interpretation der Daten.

Wenn Sie Daten kontinuierlich senden möchten, benötigen Sie eine send() - Schleife, die Bytes in den Socket pumpt, sobald Ihr Server sie hat. Wenn Sie Daten kontinuierlich lesen müssen, benötigen Sie eine Schleife, die Byte-Bytes kontinuierlich empfängt und ihnen Sinn macht.