Über einen TCP Server gesendete Bytes kommen manchmal nur unvollständig an

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    @ErfinderDesRades Das mit dem Paketsystem ist so schon richtig, ja man muss sich bei TCP nicht darum kümmern, dass alle Daten ankommen, aber vlt. will man ja mehrere Dateien gleichzeitig versenden(nicht nacheinander). Dazu muss man soetwas machen.

    VincentTB schrieb:

    _netstream.Read(New Byte(0) {}, 0, 1) 'Aus
    irgendeinem Grund ist die Client immer schneller mit dem Verschicken
    als der Server mit dem Lesen. Also muss der Server immer einen Byte
    schicken, um zu sagen, dass er bereit ist, bevor der Client das nächste
    Paket versendet

    Und warum sollte dies irgendetwas ausmachen?

    netstream.Read(recdata, 0, recdata.Length) hat einen Rückgabewert vom Typ integer, dieser gibt an, wie viele Bytes tatsächlic gelesen wurden. Deshalb solltest du darauf achten, dass alle erwarteten Bytes angekommen sind und falls nicht ggf. die restlichen Empfangen. Da sieht man dann auch den Sinn vom Offset gleich viel besser ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ok, ich habe das ganze nun wesentlich vereinfacht und ich sende und schreibe nun im ganzen:
    Client:

    VB.NET-Quellcode

    1. Dim fiSource As New FileInfo(path)
    2. Dim buffersize = 1024
    3. Dim writer As New BinaryWriter(_netstream)
    4. Using fs As New FileStream(fiSource.FullName, FileMode.Open, FileAccess.Read)
    5. Dim filelength = CInt(fs.Length)
    6. Dim TotalLengthBytes = BitConverter.GetBytes(filelength)
    7. SendPacket(TotalLengthBytes, writer)
    8. Dim SendingBuffer As Byte() = New Byte(filelength) {}
    9. fs.Read(SendingBuffer, 0, filelength)
    10. writer.Write(SendingBuffer)
    11. End Using


    Server:

    VB.NET-Quellcode

    1. Dim totallength = reader.ReadInt32()
    2. _connection.ListnerIsEnabled = False
    3. Dim currentlength = totallength
    4. Dim fs As New FileStream(localpath, FileMode.OpenOrCreate, FileAccess.Write)
    5. Dim file = reader.ReadBytes(totallength - 1)
    6. fs.Write(file, 0, file.Length)
    7. _connection.ListnerIsEnabled = True
    8. fs.Close()


    Ich denke, es ist ein bisschen besser geworden, denn die Bilder/Musikdateien, mit denen ich es ausprobiert haben, waren nicht unbrauchbar und man sah/hörte nichts von den Fehlern, aber die Hashwerte stimmen nicht überein und wenn ich ein gesendetes Archiv öffnen möchte kommt: Das ist Archiv zerstört. :(


    EDIT:
    @jvbsl
    So wie ich das sehe, ist es so, dass wenn der Client etwas sendet, aber in diesem Moment beim Server niemand liest, die Bytes verloren gehen. _netstream.Read() hält die Prozedur bei mir dann einfach nur an und wartet. Ist es nicht auch so, dass wenn der netstream 4 Bytes lesen will, aber der Server nur 3 Bytes sendet, der netstream so lange wartet, bis ein weiteres Byte gesendet wird?
    Mfg
    Vincent

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

    Dem stimme ich nicht zu. Es ist eine Tatsache, dass die Architektur völlig anders gestaltet wird und die Übertragung nicht wesentlich erschwert wird, wenn man sie entsprechend gestaltet. Wenn man dann nicht "verfrüht optimiert", kann man quasi das komplette Programmstück beginnen, weil man vor lauter Änderungen kaum noch gleiches findet, außer man verwendet eine entsprechend gleiche Schnittstelle, aber das ist für ein Client-Server-System unangemessen, denn das kann viele Clients, aber nur einen Server haben. Die Clients können aber einzelne "Surrogaten" haben, die losgelöst von der sendenden und empfangenden Instanz sind.

    Gruß
    ~blaze~
    ich kann dir nicht folgen mit Architektur, Programmstück und den Surrogaten.
    Ich hab halt mein Versuchs-Chat geschrieben, und wenn ich wollte, könnte ich da vmtl. auch eine selbstgebastelte Paketisierung noch dranmachen - das würde die Architektur überhaupt nicht ändern, oder höchstens insofern, dass der innere Aufbau der Client-Klasse komplexer würde.
    Aber mangels Bedarf erspar ich mir das - (Rule 3: "Profile before Optimization").
    Immer eingedenk der Tatsache, dass Tcp ja bereits intern paketisiert ist.

    Das ist ja grade die Gesetzmäßigkeit recht verstandener Optimierung: Code erstmal ohne Optimierung entwickeln, aber sauber und v.a. mit sauberer Architektur.
    Wenn sich dann Optimierungsbedarf zeigt, ist es auch einfach, die einzubauen - dank der ordentlichen Architektur.

    Es ist viel einfacher, von einem funktionierenden Zustand voranzuschreiten zum nächsten, leistungsfähigeren, funktionierenden Zustand.
    Als gleich alles in einem großen Wurf zu versuchen.
    Deswegen heisst es auch "Programm-Entwicklung" und nicht "Programm-Bau".

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

    @ErfinderDesRades sagen wir mal so. Optimierung hat überhaupt nichts mit Architektur zu tun. Wenn es darum geht etwas zu optimieren, dann guckt man dass Code schneller ausgeführt wird. Man optimiert bestimmte Implementierungen/Algorithmen, jedoch nicht die Architektur selbst. Beim Einbau von "Paketisierung" in deine Client Klasse würdest du dessen Architektur ändern nicht nur die Implementierung.
    Die Architektur sollte man gleich von beginn gut abstrahieren, denn es ist übersichtlicher und für später auch einfacher.
    Algorithmen optimiert man dann aber zum schluss und nur wenn nötig, das ist korrekt.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---