11 Stimmen

C# Networkstream.read()

Wie funktioniert lesen (Puffer, Offset, Länge) tatsächlich arbeiten, wenn ich die Länge zu lesen als 32 übergeben, bedeutet das, dass es halten würde blockieren, bis es die 32 Bytes erhält?

Ich verstehe, es würde zurückgeben und Ausnahme oder 0 im Falle der Socket-Ausnahme oder wenn die Verbindung geschlossen wird, bzw

Was ist, wenn der Absender nur 31 Bytes sendet, würde read dann weiterhin blockieren? Wenn das wahr ist, bedeutet das, dass read immer die ganze Zahl zurückgeben würde, die der übergebenen Länge entspricht? und wie kann ich die Zeitüberschreitung kontrollieren, wenn das verbleibende 1 Byte nicht nach einer bestimmten Zeit kommt.

Wichtig und doch nicht beantwortet

Im Gegensatz dazu, was, wenn der Absender sendet 32 Byte, versichert, dass lesen würde blockieren, bis alle 32 empfangen werden oder kann es kommen, ohne das Lesen aller 32 Bytes.

8voto

Alfred Myers Punkte 6276

Nein, sie wird nicht blockiert. Der Lesevorgang liest so viele Daten, wie verfügbar sind, bis zu der durch den Parameter size angegebenen Anzahl von Bytes. Quelle: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read.aspx

Da es nicht auf dieses zusätzliche 1 Byte wartet, sollten Sie, wenn Sie es erwarten, eine Schleife implementieren, um das Lesen des Streams fortzusetzen. Sie können die Schleife beenden, wie Sie es für richtig halten.


UPDATE: Ich habe mich geirrt, als ich sagte: "Es gibt überhaupt kein Blockieren. Wenn keine Daten zum Lesen verfügbar sind, gibt die Read-Methode 0 zurück", aber Ich hatte recht, als ich sagte, dass er nicht blockiert, wenn er darauf wartet, den gesamten Puffer zu füllen. was dem in der Frage von Kazoom beschriebenen Szenario entspricht.

Aktualisiert, um zu zeigen, dass NetworkStream.Read beim Warten auf das erste Byte blockiert, aber blockiert nicht beim Warten auf das Füllen des gesamten Puffers .

Projekte für die Konsole erstellen

Auf der einen Seite haben Sie den Hörer:

IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
TcpListener listener = new TcpListener(ep);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream s = client.GetStream();
byte[] buffer = new byte[32];
Console.WriteLine(s.Read(buffer, 0, 32));
Console.WriteLine("Press any key to continue...");
Console.Read();

Am anderen Ende wird nur ein Byte gesendet:

IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
TcpClient client = new TcpClient();
client.Connect(ep);
client.GetStream().Write(new byte[] { 60 }, 0, 1);
Console.WriteLine("Press any key to continue...");
Console.Read();

Beide Seiten werden ausgeführt, bis sie Console.Read() erreichen. Beachten Sie, dass der Listener bei Read nicht blockiert.

Der Hörer wird "1" ausgeben.

2voto

scottm Punkte 27163

Er blockiert, bis er 32 Bytes erhält oder die Verbindung geschlossen wird. Die asynchronen Methoden BeginRead() und EndRead() sollten verwendet werden, um nicht-blockierende Lesevorgänge zu ermöglichen.

Hier ist ein Beispielcode, der den Blockierungseffekt deutlich macht.

   Socket one = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    Socket two = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);

    one.Bind(ep);
    one.Listen(1);
    two.Connect("127.0.0.1", 12345);
    one = one.Accept();

    NetworkStream s = new NetworkStream(two);
    byte[] buffer = new byte[32];
    s.Read(buffer, 0, 32);

bearbeiten

Auch wenn dieser Code den Blockierungseffekt erzeugt, liegt das nur an der NetworkStream-Implementierung von Die abstrakte Read()-Methode von Stream (die übersteuert werden muss). In der Dokumentation zu Stream.Read() steht dies:

Die Implementierungen geben die Anzahl der gelesenen Bytes zurück. Der Rückgabewert ist Null nur dann, wenn die Position gerade am Ende des Streams befindet.

Deshalb blockiert der Code, wenn KEINE Daten empfangen wurden UND das Ende des Streams noch nicht erreicht wurde. Er sagt auch weiter:

Die Umsetzung wird blockiert, bis mindestens ein Byte an Daten gelesen werden kann gelesen werden kann für den Fall, dass keine Daten vorhanden sind verfügbar sind. Read gibt nur dann 0 zurück, wenn sich keine Daten mehr im Stream befinden sind und keine weiteren erwartet werden (z. B. bei einem geschlossener Socket oder Ende der Datei). Eine Implementierung steht es frei, weniger Bytes zurückzugeben, auch wenn das Ende des des Streams noch nicht erreicht wurde.

1voto

James Punkte 357

Die Frage nach der Auszeit scheint noch unbeantwortet zu sein.

Die Antwort ist, dass Sie stream.ReadTimeout und stream.WriteTimeout festlegen können, wobei stream Ihr NetworkStream-Objekt ist. Damit wird der blockierende Fall behandelt, dass überhaupt keine Antwort erfolgt. Ohne diese Werte zu setzen, wartet der Stream unendlich lange.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X