Networkstream zu... langsam?

  • VB.NET

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von Nikx.

    Networkstream zu... langsam?

    Hi :)

    Im Moment arbeite ich, wie bereits aus meiner letzten Frage sichtbar wird, an einer FTP-Verbindung via TCP.
    So weit so gut. Wäre da nicht der NetworkStream. Allgemein verstehe ich nicht, warum, wer auch immer das Teil ins Framework
    eingebaut hat, so ranzig gearbeitet hat?

    Es gibt zwar eine .Length und .Position-Methode, aber die kann nicht genutzt werden -> NotSupportedException.

    Mein Problem besteht darin: Ich sende "FEAT" und erhalte einen Mehrzeiligen Text. Der FTP-Server sendet danach noch ein
    "211 End" hinterher, welches beim lesen nicht gleich dabei ist. Okay. Ich wollte nun also eine Funktion schreiben, die liest, bis alle
    Bytes aus dem Stream gelesen sind. Is nich: Ich kann weder Length noch Position auslesen. Einzeln pro Byte vorzugehen würde
    Ewigkeiten dauern. Also nutze ich die DataAvailable-Funktion. Wenn ich alles nacheinander durchlaufen lasse, mit

    VB.NET-Quellcode

    1. Do
    2. 'Stream lesen
    3. Loop While TCPStream.DataAvailable


    dann passiert garnichts, ich bekomme kein 211 End, obwohl ja noch was im Stream steht. Ich habe mir also mal per MsgBox den
    Status von DataAvailable an verschiedenen Punkten angesehen. Nach FEAT erhalte ich meinen mehrzeiligen Text und bekomme True
    zurück. Drücke ich auf Okay steht auch das "211 End" dort. Wenn ich die MessageBoxen weglasse nicht.

    Ich habe also den Verdacht, dass es irgendwie zu schnell geht. Gibt es eine Möglichkeit das sauber zu lösen? Ich hatte nicht vor den Thread mal
    eben 2 Sekunden einzufrieren.

    Danke und liebe Grüße,
    Nikx
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Das es Length und Position nicht gibt ist logisch. Du kannst ja nicht wissen, wie viel noch vom Sender aus in den Stream reingeschrieben wird.

    Einzeln pro Byte vorzugehen würde Ewigkeiten dauern.

    Bist du dir da sicher? Ich glaube, deine CPU kann die Bytes viel schneller verarbeiten, als sie reinkommen.
    Wieso lässt man die Eigenschaften dann drin? Ist mir nicht klar.
    Beim Einzelnen vorgehen müsste ich ja alles zählen, und ich denke mal nicht dass DAS die beste Lösung ist. Ausserdem
    sagtest du ja selber, dass man nicht wissen kann, "wie viel noch vom Sender aus in den Stream reingeschrieben wird."

    Grüße
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Es kann noch alles Mögliche kommen, 211 End ist ein Beispiel. Wenn der Buffer zu klein
    ist überliest er auf die Hälfte und lässt Buchstaben weg. Warum?
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Was will ich damit? :D
    Mein Buffer ist 256, es ist doch egal was is sende? Die Antwort kommt vom Server und
    ist immer unterschiedlich.

    @Artentus:

    Klar ist das logisch ;)
    Wenn ich eine Schleife bastle die abfragt ob noch Daten da sind, mit .DataAvailable,
    dann überliest er auch, sorry :D, die Hälfte. Am Beginn fehlen Buchstaben und wenn ich den
    Puffer klein setzte fehlen zwischen den "Paketen" die ich hole auch ein paar Buchstaben.

    Aber zum Thema:
    Kann ich nicht irgendwie was einbauen, dass wartet, bis whatever bereit ist. Ich weiß ja nichtmal obs am Server
    oder am TCPCLienten oder am Stream liegt. Ich tippe auf den Stream.
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    NetworkStream besitzt kein .Peek -.-
    Du merkst allmählich was das Problem ist oder? :P
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Ja, ok, das ist dann wirklich ein Problem. :D

    Auf MSDN wirds auch so gemacht:

    C-Quellcode

    1. byte[] myReadBuffer = new byte[1024];
    2. StringBuilder myCompleteMessage = new StringBuilder();
    3. int numberOfBytesRead = 0;
    4. // Incoming message may be larger than the buffer size.
    5. do{
    6. numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
    7. myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
    8. }
    9. while(myNetworkStream.DataAvailable);
    Hab ich beim suchen schonmal irgendwo gesehen, aber hilft ja nix. Ich mache das ja
    im Prinzip ganz genauso. Nicht nur im Prinzip, ich mache das genauso.

    VB.NET-Quellcode

    1. Do
    2. Response = String.Empty
    3. StreamBytes = TCPStream.Read(Data, 0, Data.Length)
    4. Response = System.Text.Encoding.ASCII.GetString(Data, 0, StreamBytes)
    5. Console.WriteLine("Received: " & Response)
    6. Loop While TCPStream.DataAvailable
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Ich habs so versucht, es geht nicht. Er braucht Ewigkeiten.
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Versuch doch mal Local etwas zu senden und empfangen und schaue ob das Problem da auch auftritt.
    Wenn ich mit TCP arbeite, mache ich es genauso. Allerdings setze ich den Buffer auf 2048, hab nie Probleme.

    Ansonsten musst es mal probieren indem du die Länge vorher sendest.
    So mache ich es, wenn ich zb. Dateien versende und empfange.
    Du musst bedenken, dass ich keine Ahnung habe was der Server mir zurückgibt.
    Ich habe es gerade mal mit einer zusätzlichen Prüfung VOR senden der Commands versucht. Einzeln klappt das,
    aber wenn ich 5 Commands nacheinander weghaue gehts wieder nicht. Schrecklich -.-
    "Life isn't about winning the race. Life is about finishing the race and how many people we can help finish the race." ~Marc Mero

    Nun bin ich also auch soweit: Keine VB-Fragen per PM! Es gibt hier ein Forum, verdammt!
    Hi
    der Puffer blockiert doch glaub' ich, wenn keine Daten vorhanden sind. Ansonsten liest er die vorhandene Menge an Bytes in den Puffer und gibt die gelesene Anzahl zurück. Es gibt zwar auf dem TcpListener selber oder so eine Eigenschaft, die angibt, ob Daten verfügbar sind.
    Eine gute Lösung des Problems wäre, die Daten segmentiert zu verschicken, also z.B. immer blockweise maximal bis zu 4096 Bytes zu übertragen, wenn quasi asynchrone Übertragung von Nachrichten möglich ist und vor jedem Segment einen Kopf, der die Gesamtzahl der Bytes pro Packet und eine eindeutige Zuordnung, welcher Nachricht das Segment zugehörig ist, angibt. Habe das System so für ein Programm implementiert. Bei meinem System gibt es auch die Möglichkeit von einem einzigen Thread aus mehrere Clients zu handhaben, eben genau mit der oben beschriebenen Eigenschaft (BytesReceived oder so).

    Übrigens hat Stream auch die Eigenschaften CanRead, CanWrite und CanSeek, die eben angeben, ob gelesen, geschrieben und gesucht und die Länge abgefragt werden kann. Das ist eine elegante Lösung für beliebige Datenströme.

    Edit: seit FW 1.1 blockt der NetworkStream offenbar nicht mehr... :rolleyes: Offenbar sinnlos Zeit verschwendet bei meinem System.

    Gruß
    ~blaze~

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „~blaze~“ ()

    Wenn ein Befehkt geht und der zweite hintendrandann nicht mehr. Liegt es daran das er ununterbrochen sendet und der Client nicht weiß wann Befehl 1 aufhört und Befehl 2 anfängt.

    Als Übergangslösung könntest du einfach zwischen einen Befehl nen Thread.Sleep machen von 50 ms.
    Dann sollte es funktionieren.

    Zum testen erstmal höher setzen und in Schritten runtergehen mit der Zeit bis er wieder durcheinander kommt:)

    Edit:
    Hab mir eben mal dein Code mit meinen verglichen und sehe da nen Fehler.
    Du hast Response = Stream.Read()
    Mach mal: Response &= Stream.Read()

    Sonst wird ja aber der String überschritten wenn dein Buffer voll ist.

    So hängst du noch was dran.
    Vllt geht's ja dann:)

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

    @n1nja: Hier geht es um FTP, da hat man nur auf eine Seite einfluss, indem Fall auf den Client, da kannst du kein Thread.Sleep verwenden o.ä.
    Aber das ist bei FTP auch völlig egal, da FTP ein Frage-Antwort-System ist, also ein Echo-Server, da gehört, das was am Stück empfangen wird immer zu dem einen Befehl, denn ansonsten hätte man selbst dazwiscen wieder etwas gesendet...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---