TCPClient und Chunks

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    TCPClient und Chunks

    Moin,

    ich gehe an einen einfachen TCP-Server (embOS) und frage ihn nach diversen Daten.

    ​Das geht prinzipell in etwa ja so wie aus dem folgenden stark vereinfachten Code-Schnippsel hier ausm Forum.

    VB.NET-Quellcode

    1. ​i = stream.Read(bytes, 0, bytes.Length)
    2. While (i <> 0)
    3. i = stream.Read(bytes, 0, bytes.Length)
    4. End While


    Man liest die Antwort in Häppchen, sogenannten chunks. Bei mir tut das nicht wirklich. Im Moment steht ich auf dem Schlauch und weiß nicht so das Problem liegt. Kann mich jemand in die richtige Richtung stubsen?

    Typischerweise ist Bytes ein Array of Byte mit einer gewissen Dimension (512 oder 1024 oder irgendwas anderes). Bei mir liest er den ersten Chunk ein und bricht dann ab wenn das letzte Häppchen kleiner ist als die Arraylänge. Der letzte Rest geht verloren weil eine Exception geschmissen wird.

    ​Ich habe das jetzt so gelöst, dass der erste Aufruf von read 1024 Bytes liest und in der While-Schleife jeweils nur 1 Byte gelesen wird. Das ist nicht im Sinne des Erfinders, aber es tut.

    ​Habe ich in den Einstellungen irgendwas übersehen oder warum sind alle Beispiele im Netz mit dieser Chunk-Sache so aufgebaut wie oben kurz angerissen, d.h. mit z.B. 512 oder 1024 Länge. Nirgends wird ein Problem genannt, wenn z.B. 2000 Bytes in 1024er chunks gelesen werden sollen. Mein ASCII-Text, den ich lese, ist so um die 1800-1900 Bytes lang.

    Gruß

    MQ
    Also wenn du es richtig machst, hast du so viele Bytes gelesen und verarbeitet wie da sind. Es sollen immer so viele Bytes gelesen werden, wie der Buffer gross ist. Kaum eine Datei oder sontiges ist aber durch die Buffergrösse glatt teilbar, darum gibt die Funktion Stream.Read zurück wie viele Bytes gelesen werden konnten. Konnten also nur 10 Bytes gelesen werden und verarbeitest den ganzen Buffer, der aber nur 10 für dich relevante Bytes hat, kann so was auch passieren.

    Evtl. bringt es mehr, wenn du ein wenig mehr Code zeigst.


    Probier das mal aus mit einer Datei und schaue was in der Ausgabe steht. Ist zwar mit einem Filestream, aber das geht mit beidem gleich.

    VB.NET-Quellcode

    1. Using fs As New FileStream("C:/users/nothing/desktop/untitled.png", FileMode.Open)
    2. Dim buffer() As Byte = New Byte(1023) {}
    3. Dim readedBytesCount As Integer = fs.Read(buffer, 0, buffer.Length)
    4. Debug.WriteLine(readedBytesCount)
    5. While readedBytesCount > 0
    6. readedBytesCount = fs.Read(buffer, 0, buffer.Length)
    7. Debug.WriteLine(readedBytesCount)
    8. End While
    9. End Using


    Wenn die Dateigrösse durch 1024 teilbar ist sollten die letzten 4 Ausgaben so aussehen:
    1024
    1024
    1024
    0

    anderenfalls
    1024
    1024
    hier eine Zahl < 1024
    0
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „NoIde“ ()

    Aus einem Dateistream konnte ich das Problem jetzt auch nicht reproduzieren.
    Aber hey: Welche Fehlermeldung ist es denn überhaupt? Nicht, dass wir an der falschen Stelle suchen.

    btw: Warum eigentlich dieses doppelte Read? Kann man doch in die Schleife packen und es so bei einem Read belassen, wenn man ein Do...Loop While draus macht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ich finde den doppelten Read schöner, klar kann man auch Dim readedBytesCount As Integer = Something > 0 machen und in der Schleife das erste mal lesen, aber das wären um es mit Trumps Worten zu sagen "FakeNews". Der Code erzählt eine unwahre Geschichte.

    Edit: Nochmal drüber nachgedacht, man könnte auch readedcount = -1 machen und auf <> 0 testen, dann reicht auch ein read. :S
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „NoIde“ ()

    könnt kotzen

    den ganzen Nachmittag gestern und heute den Vormittag damit verbraten. Post aufgesetzt und nu. nu geht's ... fast X(

    Freitag ist's oder?

    Aber hier mal die Anzahl der pro Loop eingelesenen Zeichen:

    163
    7
    1024
    665
    7

    und mal im Klartext die ersten beiden Chunks:


    HTTP/1.1 200 OK
    Content-Type: text/xml
    Server: embOS/IP
    Expires: 30 JAN 2009 09:00:00 GMT
    Last-Modified: 30 JAN 2009 09:00:00 GMT
    Transfer-Encoding: chunked
    < Chunk-Ende

    699
    < Chunk-Ende

    Danach kommt der eigentliche Inhalt , eine XML Datei und abschließen noch ein letzter Chunk mit einer Null und zweimal CRLF.

    Soweit macht es Sinn.

    Aber

    ​die Schleife wird nicht beendet weil read ein 0 als Anzahl gelesener Bytes liefert sondern wegen einer Ausnahme mit

    {"Von der Übertragungsverbindung können keine Daten gelesen werden: Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat."}
    jo, dassis ein lausiges Problem. NetworkStreams blockieren einfach, wenn man soundsoviele Bytes lesen will, und sie wurden nicht gesendet.
    weil da wartet der, bis gesendet ist, und wenn die Nachricht aber zuende ist, wartet er für immer bzw. bis zum Timeout.

    Ich hab da eine alles erschlagende Lösung für gebastelt: TcpKommunikation + Networkstream

    Meinen StreamContainer kannste dann so ansprechen wie ein FileStream, und erzeugt am Nachricht-Ende ein EOF, und zwar ohne dass der darunterliegende NetWorkStream wirklich geschlossen wäre.

    ErfinderDesRades schrieb:

    jo, dassis ein lausiges Problem. NetworkStreams blockieren einfach, wenn man soundsoviele Bytes lesen will, und sie wurden nicht gesendet.
    weil da wartet der, bis gesendet ist, und wenn die Nachricht aber zuende ist, wartet er für immer bzw. bis zum Timeout.


    Ach herjeh!

    ​Da ich mit meinem Code nur an ein Gerät gehe, das auch immer das gleiche Gerüst sendet, kann ich auf den letzten immer gleichen Chunk prüfen und dann die Whileschleife abbrechen.

    ​Ach, es hätte so schön sein können ! :)

    Grüssle

    MQ