2009-04-21 5 views
0

Ich verwende die BeginReceive() und EndReceive() -Methode für asynchrone IO mit Sockets in .NET. Der Client sendet fortlaufende Datenpakete, und der Aufruf von EndReceive() gibt die Anzahl der gelesenen Bytes zurück.So vermeiden Sie Socket.EndReceive() blockieren, wenn keine Daten verfügbar sind

Das Problem ist, dass der Client Datenpakete sendet, aber die Datenlänge ist NULL. Dies wurde durch die Analyse des Traffics in WireShark festgestellt. Wenn die Länge der Daten Null ist, wird der Aufruf von EndReceive() dort nur blockiert.

Gibt es eine Möglichkeit, die ZERO-Länge Daten zu identifizieren, ohne tatsächlich auf EndReceive() zu blockieren?

Die ReceiveTimeout-Eigenschaft scheint auch nicht mit Async-Methoden zu funktionieren.

Beispielquellcode:

// This method runs on a separate thread 
private void ProcessRequest() 
{ 
    BeginReceive(OnClientReceive); 

    // Do some work here in a loop 
} 

// Callback method 
private void OnClientReceive(IAsyncResult result) 
{ 
    int receivedCount = socket.EndReceive(result); // this one blocks 

    // Do some work here 

    // Again start listening for data 
    BeginReceive(OnClientReceive); 
} 
+0

Ich denke, Aziz beantwortet Ihre Frage? Selbst wenn der Client Daten mit einer Länge von Null sendet, sollte EndRecieve ausgelöst und beendet werden. Wenn der Client den Socket vor Abschluss des Sendevorgangs schließt, sollte EndRecieve eine Exception auslösen, wenn die Socket-Fehler behoben sind. Ich denke, hier passiert etwas anderes ... Ich denke, es blockiert, weil der Client niemals sendet. Sind Sie sicher, dass der Client an dieselbe Steckdose sendet, die wartet? – Jess

+0

Auch wenn der Client eine Null-Senden-Nachricht abschließt, sollte er dennoch die Nachrichtenkopfzeile senden und dann sollte EndRecieve diese empfangen und 0 empfangene Bytes zurückgeben. – Jess

+0

Haben Sie die Kontrolle über den Client-Code? Können Sie den Fall erfassen, in dem Daten null sind, und einfach nicht senden? Dies könnte Ihr Problem lösen, aber ich glaube, es passiert noch etwas anderes. – Jess

Antwort

0

Sockets in .NET beschäftigt sich mit Paketen als ein kontinuierlicher Strom von Daten, nicht auf Paket-für-Paket-Basis. Deshalb wird EndReceive blockiert, bis Daten verfügbar sind oder bis die Verbindung beendet wird.

Wenn Sie die empfangenen Daten in einem Paket-für-Paket-Basis zu erfassen, ich glaube, Sie so etwas wie WinPcap Bibliothek

+0

Das ist, was ich benutze (WinpCap mit WireShark), aber das Problem besteht nicht darin, Pakete zu erfassen. Die EndReceive() Blöcke, wegen denen mein Thread blockiert. Ich möchte aus dieser Blockierung herauskommen. – A9S6

+0

Ich bin mir nicht sicher, ob ich das richtig verstehe. Sie verwenden EndReceive() im Rückruf von StartReceive(), oder? EndReceive() wartet also, bis einige Daten zu lesen sind. Wenn Sie Code ausführen möchten, unabhängig davon, ob Sie Daten haben oder nicht, sollten Sie ihn nicht in den Rückruf einfügen. Würdest du bitte erklären, was du zu erfassen versuchst? – Aziz

+0

Ja, ich habe Code, der ausgeführt wird, nachdem ich Daten von EndReceive() erhalten habe. Wenn EndReceive() jedoch blockiert, werden die Daten in der Callback-Methode nicht verarbeitet, und es wird auch keine Ausnahme ausgelöst. Es wartet nur dort. Ich denke auch, dass ReceiveTimeout nicht mit EndReceive() funktioniert. Ich möchte dieses EndReceive() zurückgeben und den Callback-Thread nicht blockieren (auch wenn es ein ZERO zurückgibt). – A9S6

1

I socket.Available

  1. if socket.Available > 0 Prozess alle Code würde überprüfen, um verwenden, müssen in Ihr Rückruf „OnClientReceive“
  2. if socket.Available = 0 nur ein Teil „// hier einige Arbeit tun“ verarbeitet
  3. einige Sperren Konflikte gelegt werden sollte
  4. zu vermeiden,