none
Datenstrom: Byte Array zu klein? RRS feed

  • Frage

  • Hallo Leute, ich benutze folgenden Code, um einen Datenstrom aufzunehmen. Leider werden nicht alle Zeichen beim ersten Schleifendurchlauf erfasst. Es bedarf derer zwei. Kann es sein, dass folgender Code das Array zu klein dimensioniert. Wieviele Zeichen können eigentlich maximal aufgenommen werden?

    double amount = 2.5 * Math.Pow(10, 5); int Amount = Convert.ToInt32(amount); Byte[] bytes = new Byte[Amount];

    string dataReceived = String.Empty; while((i = stream.Read(bytes, 0, bytes.Length)) != 0) { dataReceived = Encoding.ASCII.GetString(bytes, 0, i); . . . }





    • Bearbeitet tklustig Donnerstag, 17. Januar 2019 13:23
    Donnerstag, 17. Januar 2019 13:22

Alle Antworten

  • Hi,

    Du definierst die Größe des Array aufgrund einer Formel und nicht anhand der Länge des Streams (bspw. stream.Length anstelle von Amount). Warum?

    Da Du nicht schreibst, welche Art von Stream Du verwendest, kann man dir auch nicht sagen, ob das anders geht.

    Dein Array hat eine Größe von 250.000 Bytes (was man aber auch im Debugger selbst nachschauen kann). Mehr passt da also nicht rein, wenn der Stream also länger ist, muss man mehrfach lesen.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport





    Donnerstag, 17. Januar 2019 13:45
    Moderator
  • Nun, der Stream, der aktuell nicht als ganzes gelesen wird hat laut Explorer eine Größe von 86 KB. Er umfasst letztlich 85505 Zeichen. Das müsste in ein Array mit einer Größe von 250.000 Bytes=250 KB doch eigentlich locker reinpassen, oder? Tut es aber nicht. Warum nicht? Kann es sein, dass der Server den Stream nicht auf einmal sendet?

    • Bearbeitet tklustig Donnerstag, 17. Januar 2019 15:20
    Donnerstag, 17. Januar 2019 15:18
  • Hi,

    vorab: Du bist doch jetzt schon eine Zeit lang hier unterwegs und hast schon einige Fragen gestellt. Da solltest Du doch eigentlich schon wissen, dass wir nur helfen können, wenn Du uns auch alle relevanten Informationen zur Verfügung stellst.

    Wir arbeiten hier alle täglich in x verschiedenen Foren, Threads, ... Da kann und will sich keiner merken, was da evtl. in deinen früheren Fragen an weiteren Infos versteckt ist.

    Ein Stream kann letztendlich alles mögliche sein. Die Info, dass ein Server etwas sendet und Du nicht bspw. eine Datei ausliest oder irgendwo anders her einen komplett gefüllten MemoryStream erhältst, wäre daher schon wichtig gewesen.

    Zu deiner Frage: Ja, es kann sein, dass "der" Server die Daten block-/paketweise überträgt. Da ich aber nicht weiß, was da wo auf welchem Weg übertragen wird, ist das nur geraten.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Donnerstag, 17. Januar 2019 15:59
    Moderator
  • Hi,
    wie Stefan schon geschrieben hat, wenn mehrere Reads benötigt werden trotz großem Byte-Array, werden vom Sender mehrere Blöcke gesendet. Wenn Du das genutzte Protokoll nicht kennst, wird es schwer, eine vernünftige Lösung zu erstellen. Im konkreten Fall kannst Du auch ein kleineres Byte-Array nutzen und mehrmals Read zulassen und dann die folgenden empfangenen Bytes anhängen bis durch Schließen des Sockets durch den Sender 0 Bytes ankommen.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 17. Januar 2019 17:35
  • Sorry. Hier nunmehr die nötigen Hintergrundinformationen:

    Ich lausche und sende generell Datenstreams über das Protokoll TCP. Hier der Code:

    public void startListening() { try { int i, count, countVorgabe; double amount = 2.5 * Math.Pow(10, 5); int Amount = Convert.ToInt32(amount); Byte[] bytes = new Byte[Amount]; string dataSent = String.Empty; string dataReceived = String.Empty; string HttpOkay = "HTTP/1.1 200 OK"; string file = String.Empty; string manipulatedFile = String.Empty; string zusatz = String.Empty; ContentLength CL = new ContentLength(); //Create the ServerSocket string ip = this.GetLocalIPAddress(); _logger.Info("Succesfully got IPv4 {0} from GetLocalIPAddress()", ip); IPAddress localhost = IPAddress.Parse(ip); listener = new TcpListener(localhost, listenPort); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Listening on port {0} with IPv4 {1}", listenPort, localhost.MapToIPv4()); _logger.Info("Listening on port {0} ", listenPort); listener.Start(); mainSocket = listener.AcceptSocket(); Stream stream = new NetworkStream(mainSocket); Console.WriteLine("Client connected to Endpoint {0} via Protocoll {1}. Waiting for some Bytes... ", mainSocket.RemoteEndPoint, mainSocket.ProtocolType); _logger.Info("Client connected to Endpoint(IPv4):{0} via Protocoll:{1} ", mainSocket.RemoteEndPoint, mainSocket.ProtocolType); // Loop to receive all data sent by Requester! while((i = stream.Read(bytes, 0, bytes.Length)) != 0) { Console.WriteLine("Now, waiting 5 seconds in order to get all data from stream"); _logger.Warn("Now, waiting 5 seconds in order to get all data from stream"); Thread.Sleep(5 * 1000); // Convert data bytes to a ASCII string. dataReceived = Encoding.ASCII.GetString(bytes, 0, i); // wait for all data given according to countVorgabe in stream file = CL.FileTrimmen(dataReceived, leaveLoop); countVorgabe = CL.eruateContentLength(dataReceived, leaveLoop); count = CL.zeichenZaehlen(file, leaveLoop); _logger.Info("There have been {0} signs counted in string received and {1} given in stream", count, countVorgabe); Console.WriteLine("{0} just has been sent to server BACKBONE, which has following IP:{1}", HttpOkay, ipAdress2GetSentTo); if(countVorgabe == count) { _logger.Info("As {0} signs counted in string received and {1} given in stream are equal, loop will be exited", count, countVorgabe); //leave Streamloop break; } else { _logger.Warn("Technically programming exit from loop, although {0} signs counted in string received and {1} given in stream was unequal!", countVorgabe, count);    //leave Streamloop. Intrinsically, loop first should be exited, if upper condition will be true !! break; } } //manipulate file after having exited loop, so that stream will be completed... manipulatedFile = CL.manipulateStringForJaeschcke(dataReceived, ipAdress2GetSentTo, listenPort, leaveLoop); _logger.Info("Streamlooping just has been exited."); File.WriteAllText(LiveDirectory + filename, dataReceived); _logger.Info("Data has been written to {0}", LiveDirectory + filename); Console.WriteLine("Client received following message:"); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("{0}", dataReceived); Console.ForegroundColor = ConsoleColor.Green; // ... and send back a response byte[] msg = Encoding.ASCII.GetBytes(HttpOkay); stream.Write(msg, 0, msg.Length);

    _logger.Info("{0} just has been sent to server BACKBONE, which has following IP:{1}", HttpOkay, ipAdress2GetSentTo);

    Console.WriteLine("Client sent following message:"); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("{0}", HttpOkay); _logger.Info("CONCLUSION:Client received following message{0}{1}", Environment.NewLine, dataReceived); _logger.Info("CONCLUSION:Client sent following message{0}{1}", Environment.NewLine, HttpOkay); this.dropConnection(sendPort, manipulatedFile, ipAdress2GetSentTo); } catch(SocketException er) { . . }


    Der Code ist momentan noch in der Testphase und stark optimierungsbedürftig. Lokal unter NetcatGUI klappt alles reibungslos, in einem anderen Netzwerk gibt es jedoch die geschilderten Probleme. Ich hätte es gerne so, dass das Programm solange lauscht bis die Content-Length Vorgabe erfüllt ist, bis also countVorgabe == count true ist.

    Um diese Vorgabe zu erfüllen, habe ich bisher folgenden Ansatz:

     // wait for all data given according to countVorgabe in stream
                        if (countVorgabe == count) {
                            _logger.Info("As {0} signs counted in string received and {1} given in stream are equal, loop will be exited", count, countVorgabe);
                            //leave Streamloop
                            break;
                        }
                        else {
                            /*
                             Algorithmus zur Eruierung der richtigen Zählweise. iterationen und Increment wird später manipulateStringForJaeschcke() übergeben, damit 
                             dieser Methode klar ist, um wieviele Zeichen dekrementiert oder inkrementiert werden muss.
                             */
                            int dummyCounter = count;
                            int repeatCounter = 0;
                            int loggerAusgabe = 0;
                            if (countVorgabe > count) {
                                while (dummyCounter != countVorgabe) {
                                    iterationen++;
                                    if (!this.LeaveLoopMethod(dummyCounter, countVorgabe)) {
                                        if (repeatCounter <= 100) {
                                            repeatCounter++;
                                            dummyCounter++;
                                            _logger.Info("Decrementing:RepeatCounter has been set to {0} and count has been set to {1}", repeatCounter, dummyCounter);
                                        }
                                        else if (repeatCounter > 100) {
                                            if (loggerAusgabe < 2)
                                                _logger.Warn("Actually, loop never will be exited, 'cause counting range is bigger as +/- 100");
                                            loggerAusgabe++;
                                        }
                                        else
                                            break;
                                    }
                                }
                            }
                            else if (countVorgabe < count) {
                                Incrementing = false;
                                while (dummyCounter != countVorgabe) {
                                    iterationen++;
                                    if (!this.LeaveLoopMethod(dummyCounter, countVorgabe)) {
                                        if (repeatCounter <= 100) {
                                            repeatCounter++;
                                            dummyCounter--;
                                            _logger.Info("Incrementing:RepeatCounter has been set to {0} and count has been set to {1}", repeatCounter, dummyCounter);
                                        }
                                        else if (repeatCounter > 100) {
                                            if (loggerAusgabe < 2)
                                                _logger.Warn("Actually, loop never will be exited, 'cause counting range is bigger as +/- 100");
                                            loggerAusgabe++;
                                        }
                                    }
                                }
                            }
                            _logger.Info("Now, dummyCounter has value {0} and countVorgabe has value {1}", dummyCounter, countVorgabe);
                            count = dummyCounter;
                            _logger.Info("After {0} iterations {1} signs counted in string received and {2} given in stream are equal, so loop will be exited", iterationen - 1, count, countVorgabe);
                            if (Incrementing)
                                _logger.Info("As Incrementing has been set to {0}, parameter given to manipulateStringForJaeschcke() should be incremented", Incrementing);
                            else
                                _logger.Info("As Incrementing has been set to {0}, parameter given to manipulateStringForJaeschcke() should be decremented", Incrementing);
                            //leave Streamloop
                            break;
                        }



           private bool LeaveLoopMethod(int x, int y) {
                if (x == y)
                    return true;
                return false;
            }


    • Bearbeitet tklustig Donnerstag, 17. Januar 2019 22:16
    Donnerstag, 17. Januar 2019 18:19