NetworkStream.Schreiben Sie kehrt sofort - wie kann ich erzählen, wenn es beendet das senden von Daten?
Trotz der Dokumentation, NetworkStream.Schreiben scheint nicht zu warten, bis die Daten gesendet wurden. Stattdessen wartet er, bis die Daten kopiert wurde, um einen Puffer und kehrt dann zurück. Die Puffer übertragen wird, in den hintergrund.
Dies ist der code, den ich im moment haben. Ob ich ns.Schreiben oder ns.BeginWrite egal - beide sofort wieder zurück. Die EndWrite auch sofort zurückkehrt (was Sinn macht, da ist es beim schreiben in den send-Puffer nicht schreiben in das Netzwerk).
bool done;
void SendData(TcpClient tcp, byte[] data)
{
NetworkStream ns = tcp.GetStream();
done = false;
ns.BeginWrite(bytWriteBuffer, 0, data.Length, myWriteCallBack, ns);
while (done == false) Thread.Sleep(10);
}
public void myWriteCallBack(IAsyncResult ar)
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
ns.EndWrite(ar);
done = true;
}
Wie kann ich erkennen, Wann die Daten tatsächlich an den client gesendet?
Will ich warten, für 10 Sekunden(zum Beispiel) eine Antwort von dem server nach dem senden meiner Daten sonst nehme ich an, dass etwas falsch war. Wenn es dauert 15 Sekunden, um zu senden, meine Daten, dann wird es immer timeout, da kann ich nur mit dem zählen beginnen aus, wenn NetworkStream.Schreiben Sie kehrt, bevor die Daten gesendet wurden. Ich will anfangen zu zählen 10 Sekunden aus, wenn die Daten verlassen hat, meine Netzwerkkarte.
Datenmenge und die Zeit zu schicken, könnte es variieren - es könnte in 1 Sekunde zu senden, es könnte in 10 Sekunden zu senden, es könnte eine minute dauern, um es zu senden. Der server sendet eine Antwort, wenn Sie die Daten erhalten hat (es ist ein smtp-server), aber ich will nicht ewig warten, wenn meine Daten war ungültig und die Antwort wird nie kommen, das ist, warum ich muss wissen, ob ich warte, bis die Daten gesendet werden, oder wenn ich bin, wartet der server darauf reagieren.
Vielleicht möchte ich zeigen den status an den Benutzer, würde ich mag, um zu zeigen, "senden von Daten an server", und "warten auf Antwort vom server" - wie konnte ich das tun?
- Haben Sie versucht, NetworkStream.Schreiben Sie mit einem 100MB Paket?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin kein C# - Programmierer, aber die Art, wie Sie gefragt haben, diese Frage ist etwas irreführend. Der einzige Weg zu wissen, wenn Ihre Daten "empfangen", für jede sinnvolle definition von "empfangen", ist eine Besondere Bestätigung-Nachricht in Ihrem Protokoll gibt die Daten vollständig bearbeitet.
Die Daten nicht "verlassen" Ihre Netzwerk-Karte, genau. Der beste Weg, zu denken, der Ihr Programm die Beziehung zu den Netzwerk:
Einer Liste von Dingen, die sein könnten, die "viel verwirrendes Zeug":
So, wenn Sie auf einer virtuellen Maschine, die gehostet wird unter einem anderen Betriebssystem, das eine software-firewall, die ist die Steuerung der virtuellen Maschine, Netzwerk, Verhalten - wenn die Daten "wirklich" verlassen Sie Ihren Netzwerk-Karte? Selbst im best-case-Szenario, viele dieser Komponenten können drop ein Paket, das Ihre Netzwerk-Karte brauchen, um wieder zu übertragen. Es hat "die linke" Ihre Netzwerk-Karte, wenn die erste (erfolglose) Versuch gemacht worden ist? Die meisten Netzwerk-APIs würde sagen, Nein, es wurde nicht "geschickt", bis Sie das andere Ende gesendet hat, eine TCP-Bestätigung.
Sagte, die Dokumentation für NetworkStream.Schreiben scheint zu zeigen, dass Sie nicht zurückkehren wird, bis es hat mindestens initiierte den "senden" - Vorgang:
Natürlich, "gesendet" ist etwas vage für die Gründe, die ich oben gab. Es gibt auch die Möglichkeit, die Daten "wirklich" geschickt, die durch Ihr Programm und erhielt von der peer-Programm, aber die peer-Absturz oder sonst eigentlich nicht die Daten verarbeiten. So sollte man eine
Write
gefolgt von einemRead
einer Nachricht, wird nur abgegeben werden, die von Ihrer peer, wenn es tatsächlich die Nachricht verarbeitet.Write(bytes)
genannt, später, wenn das TCP-ACK empfangen wurde von anderen peer, dann eine Meldung sollte pop-up, das ist die Frage-Besitzer möchte.TCP ist ein "zuverlässiger" - Protokoll, was bedeutet, dass die Daten empfangen werden, die am anderen Ende, wenn es kein socket Fehler. Ich habe gesehen, zahlreiche Anstrengungen auf den zweiten erraten von TCP mit einer höheren Ebene der Bestätigung der Anmeldung, aber IMHO ist dies in der Regel eine Verschwendung von Zeit und Bandbreite.
In der Regel das problem, das Sie beschreiben, ist behandelt durch normale client/server-design, das in seiner einfachsten form geht so...
Sendet der client eine Anfrage an den server und macht ein blockierender read auf dem socket wartet auf irgendeine Art von Reaktion. Wenn es ein problem mit der TCP-Verbindung dann, das Lesen wird abgebrochen. Der client sollte auch ein timeout zu erkennen, alle nicht-Netzwerk-Problem mit dem server. Wenn die Anforderung fehlschlägt oder Zeiten, dann kann der client wiederholen, einen Fehler melden, etc.
Sobald der server verarbeitet die Anfrage und schicken die Antwort, die er in der Regel nicht mehr kümmert, was passiert - auch wenn die Buchse geht Weg, während die Transaktion - weil es bis zu dem client zu initiieren, jede weitere Interaktion. Ich persönlich finde es sehr tröstlich zu sein, der server. 🙂
Im Allgemeinen, ich würde empfehlen, das senden einer Bestätigung von dem client sowieso. So können Sie 100% sicher, dass die Daten empfangen wurden, und erhielt richtig.
Wenn ich raten müsste, der NetworkStream hält die Daten geschickt haben, sobald Sie die Hände der Puffer aus, um die Windows-Socket. Also, ich bin mir nicht sicher, es gibt einen Weg, das zu erreichen, was Sie wollen über TcpClient.
Ich kann nicht denken Sie an ein Szenario, in dem NetworkStream.Schreiben würde nicht senden Sie die Daten an den server so bald wie möglich. Abgesehen von massiven überlastung des Netzwerks oder Trennung, sollte es am Ende auf das andere Ende innerhalb einer angemessenen Zeit. Ist es möglich, dass Sie ein Protokoll-Problem? Zum Beispiel mit HTTP-request-Header muss am Ende eine leere Zeile, und der server wird nicht senden Sie die Antwort bis einer Auftritt-ist das Protokoll verwendet eine ähnliche end-of-message-Eigenschaft?
Hier einige saubereren code als die ursprüngliche version, entfernen die Delegierten, Feld und Faden.Schlafen. Es preforms in exakt der gleichen Weise funktional.
Sieht aus wie die Frage geändert wurde, während ich das oben geschrieben. Die .WaitOne() kann helfen, Ihre timeout-Problem. Es kann überschritten werden, einen timeout-parameter. Dieser ist ein fauler warten -- der thread wird nicht wieder geplant, bis das Ergebnis fertig ist, oder der timeout abläuft.
Ich versuche zu verstehen, die Absicht .NET NetworkStream-Designer, und Sie müssen es design auf diese Weise. Nach dem Schreiben, die Daten zu senden, werden nicht mehr behandelt .NET. Daher ist es vernünftig, dass Schreiben gibt sofort (und die Daten werden versandt von NIC einige Zeit bald).
So in Ihre Applikation zu entwerfen, sollten Sie diesem Muster Folgen andere, als zu versuchen, es zu machen, arbeiten Sie Ihren Weg. Verwenden Sie zum Beispiel eine längere Auszeit, bevor Sie empfangen auch keine Daten aus dem NetworkStream zu kompensieren, die Zeit verbraucht, bevor Sie Ihren Befehl verlassen der NIC.
In allem ist es schlechte Praxis zu schwierig, code ein timeout-Wert in source-Dateien. Wenn der Wert für den timeout ist konfigurierbar zur Laufzeit, sollte alles gut funktionieren.
Wie über die Verwendung der Flush () - Methode.
Sollten sicherstellen, dass die Daten geschrieben, bevor Sie fortfahren.
Unten .net ist die windows-sockets die TCP verwenden.
Verwendet TCP ACK ' - Pakete Benachrichtigen Sie den Absender, die Daten erfolgreich übertragen wurden.
Damit der Absender-Maschine weiß, Wann Daten übertragen worden sind, aber es gibt keine Möglichkeit (von der ich mir bewusst bin), um die Informationen in .net.
Bearbeiten:
Nur eine Idee, noch nie ausprobiert:
Write () - Blöcke nur, wenn die buchsen Puffer voll ist. Wenn wir also niedriger, die Puffer-Größe (SendBufferSize) auf einen sehr niedrigen Wert (8? 1? 0?) können wir bekommen, was wir wollen 🙂
Vielleicht versuchen Sie
tcp.NoDelay = true