Laden...

Mehrere Daten nach NetworkStream trennen

Erstellt von Backel vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.927 Views
B
Backel Themenstarter:in
6 Beiträge seit 2012
vor 11 Jahren
Mehrere Daten nach NetworkStream trennen

Schönen guten Tag liebe Mitglieder

Ich hab mal eine kleines Problem und diesbezüglich eine Frage^^ und zwar...

Problem:

Ich habe eine Client-Server Verbindung und sende von seitens des Clients eine Bytearray von 1MB-5MB über einen Networkstream.

Der Server Liest diese Daten ein und speichert sie als .txt .....

Soweit is alles gut aber jetzt kommt das Problem

Ich möchte nun 2 verschiedene Bytearray von seiten des Clients senden(schnell nacheinander) und der Server muss erkennen wann die erste Bytearray zuende ist.

Wie kann ich dem Server klarmachen das die erste Bytearray zuende ist und er alle danachfollgenden Bytes in einer neuen .txt speichert??

Ich hoffe meine Frage wird verstanden und mir kann geholfen werden^^

MfG Ich

6.911 Beiträge seit 2009
vor 11 Jahren

Hallo Backel, willkommen im Forum,

eine einfache Möglichkeit dazu ist ein "Protokoll" zu verwenden, indem eine klar definierte Folge von Bytes als Terminator verwendet wird. Diese Folge von Bytes sollte aber sonst nicht im zu übertragenden Strom vorhanden sein.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
Backel Themenstarter:in
6 Beiträge seit 2012
vor 11 Jahren

Vielen Dank für die schnelle Antwort nur habe Ich da noch eine Frage ....

Wenn ich eine Bytefolge als Terminator verwende, muss doch der Server jedes bei ihm ankommende Byte erst untersuchen was bei 5MB lange dauert oder irre ich mich da?

6.911 Beiträge seit 2009
vor 11 Jahren

Hallo Backel,

ich hab vorhin noch eine (vllt. üblichere) Möglichkeit vergessen zu erwähnen. Sofern möglich bzw. die Länge der Bytearrays vorher schon bekannt sind, so sende vor Beginn der eigentlichen Nachrichten einen "Header", der aus fest definierter Anzahl an bytes besteht, und in dem angegeben wo sich die Bytearrays trennen. So kannst du dann einfach per Index und Offset auf Empfängerseite auslesen. Das ist einfacher.

Wie speicherst du denn den Stream in der txt-Datei?
Hier kannst du dich einhaken, indem dort die Bytes geprüft werden. Am besten durch eine eigene Klasse die den Stream auf Terminator parsed und dann ein IEnumerable<byte[]> für die jeweiligen Bytearrays zurückgibt.
Bei 5MB sollte das keine Leistungsprobleme geben.

Aber die Lösung über den Header ist einfacher und sorry, dass ich das vorher unterschlagen habe.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

106 Beiträge seit 2011
vor 11 Jahren

Hallo gfoidl,

sollte das der Stream nicht von selber wissen? Wenn ich vom Stream lese und er mir nichts mehr zurückliefert, dann kann ich doch davon ausgehen das der Stream komplett übertragen wurde oder nicht? Ansonsten müsste er mir ja eine Exception werfen, wenn ich aus irgendeinem grund nicht mehr lesen kann.
Hab grad diesbezüglich die msdn überflogen und die empfiehlt unter anderem "NetworkStream.DataAvailable" für sowas zu nutzen.

MfG
Rabban

W
872 Beiträge seit 2005
vor 11 Jahren

Im Stream solltest Du keine Annahmen machen, was genau passiert.
Ist bei Dir "nichts zurueckliefern" ein Timeout? Wenn Du ohne Timeout liest, dann blockiert das Lesen vom Stream.
Vorher die Groesse mitteilen, ist die einzige saubere Vorgehensweise.
Ist auch performant, damit gleich die richtige Byte-Array Groesse auf Seiten des Empfaengers initialisert wird.

B
Backel Themenstarter:in
6 Beiträge seit 2012
vor 11 Jahren

Also erstmals vielen Dank an gfoidl

Also soweit habe ich es, nur muss ich mir noch überlegen wie ich das mache, dass wenn der Server erst 1MB von 5MB gelesen hat weitermacht bis er genau 5MB hatt.
Aber das dürfte nich schwer sein.
Nochmals vielen Dank an dich^^

@Rabban das Problem ist eben das wenn ich dem Server mehrere Daten nacheinander schicke und diese sich stauen weil er zulangsam ist is alles nur noch eine Datei.

106 Beiträge seit 2011
vor 11 Jahren

Eins vorweg, ich habe keinerlei Erfahrung mit .Net.Sockets, nur etwas mit Wcf und da funktioniert es genauso wie ich es geschildert habe. Habe hier meine Frage nur aus reiner Neugier angebracht, ich hoffe es ist nicht zu sehr OT.

Ist bei Dir "nichts zurueckliefern" ein Timeout? Wenn Du ohne Timeout liest, dann blockiert das Lesen vom Stream.

Stream.Read gibt die Anzahl der Bytes zurück die gelesen wurden, laut msdn gibt es 0 zurück wenn der Stream komplett gelesen wurde. Das meine ich mit "nichts zurückliefern".
Sollte man aus irgendeinem anderen Grund nicht mehr den Stream lesen können, so wird eine Exception geworfen. 0 ist somit immer das Signal wenn man fertig ist.

Anschliessend würde ich dann einfach einen zweiten Stream öffnen und die andere Datei übertragen. Allerdings scheint das bei .Net.Sockets einiges anders zu laufen als bei Wcf(Wie ich das bis jetzt aus dem Thread hier verstehe).

das Problem ist eben das wenn ich dem Server mehrere Daten nacheinander schicke und diese sich stauen weil er zulangsam ist is alles nur noch eine Datei.

Benutzt du dann einen oder zwei Streams um die beiden Dateien zu übertragen?

MfG
Rabban

Ps: sorry falls ich zu sehr OT werde, wenn es überhand nimmt gebt einfach kurz bescheid.

C
2.121 Beiträge seit 2010
vor 11 Jahren

@Rabban das Problem ist eben das wenn ich dem Server mehrere Daten nacheinander schicke und diese sich stauen weil er zulangsam ist is alles nur noch eine Datei.

Deswegen kann man auch nicht erkennen wann "nichts mehr" kommt und dann doch wieder was von der nächsten Datei beginnt. Das ist so wie du am Telefon auch nicht weißt wann der andere nichts mehr zu sagen hat, weil nach jeder Sprechpause doch wieder was kommen kann.

Zu deiner Befürchtung. Lass dein Programm testweise 5 MB nach einem Endezeichen durchsuchen und mess nach wie lang das dauert.

In WCF gibt es ein Protokoll. Da läuft im Hintergrund einiges ab um zu erkennen wann alle Daten da sind. Erst dann wird die Methode mit den Daten aufgerufen.

B
Backel Themenstarter:in
6 Beiträge seit 2012
vor 11 Jahren

Also ich habe es jetzt so gemacht das ich als erstes eine Bytearray an den Server sende in der die Länge der Datei steht die danach gesendet wird.

Der Server liest dann weiter im Stream und nimmt als Count die Länge der Datei die er bekommen hat.

Sollten die gelesenen Bytes nicht mit der Länge übereinstimmen Rechne ich "Länge der Datei - gelesene Bytes = Länge der Datei" und lese weiter im Stream.

Das eben solange bis "gelesene Bytes = Länge der datei"

Das müsste doch soweit stimmen oder?

Weil ich irgendwo noch einen Fehler habe ihn aber nicht finde.

Hier ist mal der Code .... ich weiß das er nicht grade gut ist aber is mein erstes prog in c#
würde mich freuen wenn wer den fehler findet da ich nicht weiter komme sobald eine datei in die 2te schleife kommt wird sie ziehmlich groß ( ich schicke 5x5MB daten erstellt werden meist 4x 5MB daten und 1X34MB)


            while (true)
            {
                anzahl = new byte[7];

                bytesRead2 = MessageStream.Read(anzahl, 0, anzahl.Length);

                if (bytesRead2 == 7)
                {
                    anzahlbyte = Convert.ToInt32(encoder.GetString(anzahl, 0, bytesRead2));
                    newFileName = System.IO.Path.GetRandomFileName();
                }

                message = new byte[anzahlbyte];
    
                int laengemessage = message.Length;
              
                bytesRead = MessageStream.Read(message, 0, laengemessage);
                
                if (bytesRead == 0)
                {

                   break;
                }

                StreamWriter WStream = new StreamWriter(activeDir + "/" + newFileName + ".txt", true);
                WStream.Write(encoder.GetString(message, 0, bytesRead));

                while (bytesRead != laengemessage)
                {
                    laengemessage =  laengemessage - bytesRead ;

                    bytesRead = MessageStream.Read(message, 0, laengemessage);
                    WStream.Write(encoder.GetString(message, 0, laengemessage));
                   
                }

                WStream.Close();
                
                newFileName = System.IO.Path.GetRandomFileName();  
            }



106 Beiträge seit 2011
vor 11 Jahren

is mein erstes prog in c#

Gibt es einen Grund warum du dich gegen Wcf entschieden hast? Mit Wcf sollte die Kommunikation bedeutend einfacher zu handhaben sein.

MfG
Rabban

B
Backel Themenstarter:in
6 Beiträge seit 2012
vor 11 Jahren

Ja der Grund ist das dies meine Aufgabe ist^^

B
Backel Themenstarter:in
6 Beiträge seit 2012
vor 11 Jahren

ok ich habe den fehler gefunden^^ ich bin ja soooooo blöd


 WStream.Write(encoder.GetString(message, 0, laengemessage));

muss zu


                   WStream.Write(encoder.GetString(message, 0, bytesRead ));

nochmals danke an auch alle