C C# - Daten auf dem PC empfangen

Janiiix3

Aktives Mitglied
28 Sep 2013
1.301
10
38
Hannover
Sprachen
C, C#
Guten Nabend,

ist villeicht nicht ganz so richtig platziert hier..
Aber eventuell kann mir ja doch jemand helfen oder hatte sogar schon mal nen ähnliches Problem.

Mein Problem:
Bin gerade dabei mir ein kleines PC Tool zu schreiben welches Daten einsammelt und auswertet.
Da ist auch schon das eigentliche Problem. Das einsammeln klappt bei höheren Baudraten deutlich besser als bei kleineren (<= 9600).

Ich habe ehrlich gesagt keine Ahnung mehr was ich noch anstellen kann damit es sauber ohne ein "Delay" funktioniert..

Achja.. Wenn ich ein "Delay" in das Event mit einbaue, sieht es bis jetzt so aus das alles so ankommt und ausgewertet wird wie es eigentlich soll.

Hier mal der Kode ( ist für den PC )


CodeBox C und C++
        public void Client_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            /* Protokoll
             *
             *  Startbyte[0]                    : '-'
             *  Startbyte[1]                    : '+'
             *  Nachrichtenlänge[2]             : 0..255
             *  Anzahl Nutzdaten[3]             : 0..255
             *  Daten Type[4]                   : 0..6
             *  Nachrichten Identifikation[5]   : 0..255
             *  Funktionsrückgabe Code[6]       : 0..255
             *  Checksumme[7]                   : 0..255
             *  Nutzdaten[8..n]                 : 0..255
            */

            Thread.Sleep(10);

            /*  Empfangene Daten abholen
            */
            try
            {
                Length += Client.Read(buffer, Length, 250);
            }
            catch { }

            /*  Kommando Start Parsen
             *  Rückgabewert: - 1 = Kein Start gefunden..
            */
            int index = Parser.ParseStart(buffer);
            if (index != -1)
            {
                /*  Anzahl der zu empfangenen Bytes auslesen
                    * HIER WIRD NOCH KEIN CRC BERECHNET!
                    * Es könnten Übertragungsfehler nicht erkannt werden..
                */
                BytesToReceive = buffer[index + (byte)Cmd.Communication_Header_Enum.CMD_HEADER_LENGHT];
            }

            /*  Wurden alle Bytes empfangen?
                *  Wenn nicht, direkt wieder raus hier!
            */
            if (Length < BytesToReceive)
            {
                return;
            }
            else
            {
                Length = 0;
                BytesToReceive = 0;
            }

            /*  Kommando untersuchen..
            */
            Parser.Parse(buffer, ref Cmd.CommandoParsed);
        }
 

addi

Mitglied
2 Sep 2013
115
4
18
Hamminkeln
Sprachen
BascomAVR, C, Assembler
Hmmm...wo/wie wird der com port konfiguriert? Timeoutparamer setzen und einen rückgabewert bekommen.
73 addi
 

Janiiix3

Aktives Mitglied
28 Sep 2013
1.301
10
38
Hannover
Sprachen
C, C#
Hey Addi,

ich arbeite ohne Timeout da die Daten im Event asynchron eingelesen werden.
 

TommyB

Premium Benutzer
17 Mai 2010
1.803
65
48
35
127.0.0.1 ;)
Sprachen
Assembler, LunaAVR, VB.Net, Python, C#
Sehr instabiles Konstrukt, merkste ja selber. Was ist wenn dein Length über Buffer.Length liegt? Crash.
Was passiert wenn Length bereits auf 490 steht, Buffer.Length aber nur 500 Bytes groß ist? Du liest nur maximal 10 Bytes ein. Fragmentierung.
Was passiert wenn dein Datenpaket was du haben willst 17 Bytes lang ist, du aber 19 empfängst? Ist ja ein Paket empfangen worden, also machst du n Buffer Reset, löscht also die 2 zu viel empfangenen Bytes.
Dazu weiß ich nicht wie lange der buffer, also die alten Daten darin, gültig sind.

Dein Problem wird sein, du erwartest (jeder [] Block ist ein Read):
[12345678] [12345678]
Du empfängst aber:
[1] [2345] [6781] [23] [456] [78]
Die 1 wird entfernt, also arbeitest du weiter mit:
[23] [456] [78]
was eine Protokollverletzung ist.

Daher: Vernünftig sammeln und dann auswerten. Dafür wären Stichworte FiFo Buffer, RingBuffer, zur Not auch ne List(Of Byte).
 

Janiiix3

Aktives Mitglied
28 Sep 2013
1.301
10
38
Hannover
Sprachen
C, C#
Du hast natürlich in allen Punkten recht.
Habe ein wenig was angepasst. Jetzt funktioniert es einwandfrei. Die Pakete kommen an wie es soll.



CodeBox C und C++
        private static int BytesIsReceive = 0;
        private static uint BytesToReceive = 0;
        private static byte[] buffer = new byte[256];
        public void Client_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            /* Protokoll
             *
             *  Startbyte[0]                    : '-'
             *  Startbyte[1]                    : '+'
             *  Nachrichtenlänge[2]             : 0..255
             *  Anzahl Nutzdaten[3]             : 0..255
             *  Daten Type[4]                   : 0..6
             *  Nachrichten Identifikation[5]   : 0..255
             *  Funktionsrückgabe Code[6]       : 0..255
             *  Checksumme[7]                   : 0..255
             *  Nutzdaten[8..n]                 : 0..255
            */
            /*  Empfangene Daten abholen
            */
            try
            {
                BytesIsReceive += Client.Read(buffer, BytesIsReceive, Client.BytesToRead);
            }
            catch
            {
                return;
            }

            /*  Kommando Start Parsen
             *  Rückgabewert: - 1 = Kein Start gefunden..
            */
            uint HeaderIndex = Parser.ParseStart(buffer);
            if (HeaderIndex >= 0)
            {
                /*  Anzahl der zu empfangenen Bytes auslesen
                    * HIER WIRD NOCH KEIN CRC BERECHNET!
                    * Es könnten Übertragungsfehler nicht erkannt werden..
                */
                BytesToReceive = buffer[HeaderIndex + (byte)Cmd.Communication_Header_Enum.CMD_HEADER_LENGHT];
            }
            /*  Wurden alle Bytes empfangen?
                *  Wenn nicht, direkt wieder raus hier!
            */
            if (BytesIsReceive < BytesToReceive)
            {
                return;
            }
            if (BytesIsReceive == BytesToReceive)
            {
                /*  Kommando untersuchen..
                */
                int ParserResult = Parser.Parse(buffer, ref Cmd.CommandoParsed);
                //WriteDebugBuffer(buffer, (int)BytesToReceive, BytesIsReceive, ParserResult);
                DataReceivedEventFunc(buffer,BytesToReceive);
                BytesIsReceive = 0;
                BytesToReceive = 0;
            }
            else if (BytesIsReceive > BytesToReceive)
            {
                BytesIsReceive = 0;
                BytesToReceive = 0;
            }
        }
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)