Forum: PC-Programmierung Problem mit winsock


von Markus (Gast)


Lesenswert?

Hallo

ich hab ein kleines Problem mit recv. ich übergebe der Funktion z.B. 
einen buffer von 100 Zeichen und empfangen werden aber nur 10 oder 
irgendeine andere Anzahl von Zeichen, was mache ich falsch

Gruß, Markus

von thomas (Gast)


Lesenswert?

hi,
Deine Angaben sind schon etwas spärlich!

Über winsock (generell TCPIP) werden die Daten immer paketweise 
verschickt.

Kleine Datenmengen gehen auf einen Rutsch durch, größere werden 
stückeweise verschickt.

du solltest dir ein "endzeichen" einfallen lassen und solange die Daten 
sammeln, bis dein endzeichen da ist.

Wenn du noch schreibst, in welcher Progammiersprache, dann kann man noch 
besser helfen.

mfg
Thomas

von Markus (Gast)


Lesenswert?

ich schreibe in C, hab mir da eine Funktion definiert.

char * readData(int buf)
{
long byte = recv(sock,data,...)

 return data[byte]='\0';

}


Nur irgendwie ist "data" jetzt immer ein leerer String, obwohl Daten 
vorhanden sind. Ich habe zur Überprüfung das Terminal von Herkules 
benutzt, da funktionierts einwandfrei.

von (prx) A. K. (prx)


Lesenswert?

TCP oder UDP?

von Markus (Gast)


Lesenswert?

ich will es für alle beiden Protokolle machen. Der Unterschied besteht 
ja soweit ich weiss nur in der Verwendung einer anderen Funktion, statt 
recv heißt es dann eben recvfrom.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> Der Unterschied besteht
> ja soweit ich weiss nur in der Verwendung einer anderen Funktion, statt
> recv heißt es dann eben recvfrom.

Ui.
Diese Aussage hinkt gewaltig.
Das ist für mich ungefähr so, wie wenn einer sagt, der Unterschied 
zwischen Free-Climbing und 'Mit-der-Seilbahn-auf-den-Berg-fahren' 
besteht in einer anderen Rucksackform.

von JojoS (Gast)


Lesenswert?

bei TCP musst du solange in einer Schleife lesen bis
- alle Zeichen angekommen sind: dazu den pos. return Wert von recv auf 
den Lesezeiger oder Bufferindex aufaddieren und die Anzahl von der 
Sollanzahl abziehen bis die Diff. 0 ist
- oder recv eine 0 oder einen Fehler zurückliefert, dann Verbindung 
schliessen und wieder connect oder listen starten

von Markus (Gast)


Lesenswert?

mir ist der Unterschied zwischen TCP und UDP schon klar. Mein Problem 
ist aber die recvfrom Funktion, diese gibt mir zwar die Anzahl der Bytes 
zurück, z.B. 25 aber wenn ich die Daten dann ausgeben will ist der 
String seltsamer weise manchmal leer. Ich steuere ja ein Messgerät an, 
ich schicke ein Befehl hin (funktioniert) und warte auf die Bestätigung 
und danach auf die Daten. Manschmal geht es auch teilweise, dann kann 
ich z.B. die Befehlsbestätigung auslesen, nur eben nicht immer. Das will 
mir nicht in den Kopf.

von Karl H. (kbuchegg)


Lesenswert?

> mir ist der Unterschied zwischen TCP und UDP schon klar. Mein Problem
> ist aber die recvfrom Funktion, diese gibt mir zwar die Anzahl der Bytes
> zurück, z.B. 25 aber wenn ich die Daten dann ausgeben will ist der
> String seltsamer weise manchmal leer. Ich steuere ja ein Messgerät an,
> ich schicke ein Befehl hin (funktioniert) und warte auf die Bestätigung
> und danach auf die Daten. Manschmal geht es auch teilweise, dann kann
> ich z.B. die Befehlsbestätigung auslesen, nur eben nicht immer. Das will
> mir nicht in den Kopf.

Dein Fehler ist in der Anschauung, dass du mit einem recv die Daten 
genau so bekommst, wie der Sender sie weggeschickt hat. Dem ist nicht 
so.
Der ganze Netzwerkunterbau kann die Daten in mehrere Pakete aufteilen 
und getrennt auf den Weg schicken.
Es kann auch sein, dass der Netzwerkunterbau schon den Anfang der Daten 
in einem Paket weggeschickt hat, während der Datenerzeuger eine kleine 
Pause eingelegt hat um die nächsten Daten für das (seiner Meinung nach) 
immer noch gleiche Paket zusammenzustellen.

Du brauchst eine Minimalform eines Protokolls. Ohne geht es nicht.
Entweder der Sender schickt ganz am Anfang mit, wieviele Bytes er zu 
senden gedenkt oder in den Daten ist eine Markierung drinnen "Jetzt ist 
der Datensatz komplett".

Deine Leseroutine muss unter Umständen recv mehrmals aufrufen um den 
Datensatz wieder komplett zusammenzustellen. Und genau dafür benötigst 
du vom Sender noch zusätzliche Information, wann das der Fall ist. Eben 
dann, wenn die Anzahl der Bytes übertragen wurde bzw. wenn die Daten 
mittels einer Markierung als zu Ende markiert wurden.

UDP ist dann noch ein ganz anderes Thema. Da können deine Daten, so sie 
in mehreren Paketen aufgeteilt sind, in beliebiger Reihenfolge 
daherkommen; da kann dann auch schon mal ein Datenpaket fehlen etc. 
Sprich: Du kannst dich auf gar nichts mehr verlassen.

von Markus (Gast)


Lesenswert?

ja du hast recht, mein Messgerät schickt zuerst ein Byte, welches die 
Anzahl der nächsten dazugehörigen Bytes beschreibt. An Mehrfach-Aufruf 
hab ich schon gedacht, aber das ist ja erst der nächste Schritt. ich 
sehe ja auch Daten, wenn ich am Puffer rumspiele, also ihn z.B. 50 
setze. Ich hatte mir gedacht, wenn ich ihn auf 1 setze kann ich dann 
immer ein Byte auslesen, da bekomm ich aber einen Socket_ERROR.

Und eine andere Frage, ich habe auch noch das Problem das der 
Befehlssatz meines Messgerätes auf hexadezimalzahlen beruht. Dies hab 
ich gelöst das ich in die ASCII-Tabelle geschaut habe und das 
entsprechende Aquivalent zur entsprechenden Hexadezimalzahl gesucht und 
als String bei sendto übergeben habe, ist aber sehr mühselig, gibt es 
eine Funktion in C mit der man Hexadezimalzahlen in einen String mit 
ASCII-Zeichensatz umwandeln kann oder bzw. gibt es eine Möglichkeit 
einen String so zu markieren das recv versteht, das es sich um 
hexadezimalzahlen handelt und nicht um den ASCII Zeichensatz.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> ja du hast recht, mein Messgerät schickt zuerst ein Byte, welches die
> Anzahl der nächsten dazugehörigen Bytes beschreibt. An Mehrfach-Aufruf
> hab ich schon gedacht, aber das ist ja erst der nächste Schritt.

Nein, das ist nicht der nächste Schritt.
Das ist der erste Schritt:
Aus den einlangenden Paketen wieder einen Datenstrom zu machen, aus dem 
die Datensätze herausgefischt werden.

> einen String so zu markieren das recv versteht, das es sich um
> hexadezimalzahlen handelt und nicht um den ASCII Zeichensatz.

Auf dieser Ebene gibt es keine Strings mehr.
Da gibt es nur noch Bytes. Was immer du an Bytewerten in dein Bytefeld 
hineinstopfst, bleibt auch so drinnen. Du Tatsache, dass du hier von 
Strings redest, lässt mich schon Schlimmes vermuten.

PS: Lass dich nicht davon verwirren, dass sendto auf deinem System ev. 
einen char* als Argument nimmt. char* war früher die übliche 
Schreibweise für 'Pointer auf alles'. Heutzutage würde man einen void* 
dafür benutzen, aber es ist nichts schwerer auszurotten als alte 
Gewohnheiten bzw. Kompatibilitäten.
1
  unsigned char SendBuffer[10];
2
3
  SendBuffer[0] = 0x12;
4
  SendBuffer[1] = 0x78;
5
  SendBuffer[2] = 'd';
6
  SendBuffer[3] = 'e';
7
8
  sendto( serverSocket, SendBuffer, 4, ...
9
10
  //
11
  // oder:
12
  // sendto( serverSocket, (char*)SendBuffer, 4, ...

von Markus (Gast)


Lesenswert?

danke für die hilfreichen Antworten, ich werd ma schaun ob ich es 
hinbekomme, das mit dem char hat mich wirlich etwas Wirre gemacht.

von gast (Gast)


Lesenswert?

eine Frage muss ich doch noch stellen, von meinem Messgerät(laut manual) 
müsste ich eigentlich hexadezimale Zahlen empfangen, das Problem ist nur 
das diese Hexadezimalzahlen von recv wieder als ASCII-Zeichenfolge 
ausgegeben werden .z.B FO wird als ö ausgegeben, wie bekomme ich das nun 
hin, das als hexadezimal zeichen auszugeben. zu meiner Verdeidigung 
möchte ich noch sagen, das ich kein Informatiker der Programmierer bin. 
Ist alles Neuland für mich

von Karl H. (kbuchegg)


Lesenswert?

gast schrieb:
> eine Frage muss ich doch noch stellen, von meinem Messgerät(laut manual)
> müsste ich eigentlich hexadezimale Zahlen empfangen, das Problem ist nur
> das diese Hexadezimalzahlen von recv wieder als ASCII-Zeichenfolge
> ausgegeben werden .z.B FO wird als ö ausgegeben, wie bekomme ich das nun
> hin, das als hexadezimal zeichen auszugeben. zu meiner Verdeidigung
> möchte ich noch sagen, das ich kein Informatiker der Programmierer bin.
> Ist alles Neuland für mich

Von deinem Messgerät kommen weder Texte noch hexadezimale Zahlen noch 
sonst irgend etwas. Von deinem Messgerät kommen Bytes, die einen Wert 
haben.
Wie du diese Bytes anzeigst ist dein Bier.
Ob F0 als ö ausgegeben wird oder als 0xF0 oder als 240 oder als 
Pixelmuster, hängt ausschliesslich davon ab, wie du ausgibst. Deswegen 
ändert sich aber der Bytewert nicht. Der Bytewert ist immer dergleiche: 
die oberen 4 Bit auf 1, die unteren 4 Bit auf 0

Im Rechner gibt es keine Texte, es gibt keine Hexwerte, es gibt keine 
Dezimalzahlen. Es gibt ausschliesslich Bitmuster! Was diese Bitmuster 
bedeuten, interessiert den Rechner nicht. Ein Bitmuster kann alles 
mögliche sein: Sie kann ein Opcode sein, der einen Befehl für die CPU 
kodiert. Es kann mithilfe des ASCII Codes als ein bestimmmter Buchstabe 
(bei der Ausgabe) interpretiert werden. Nimmt man anstelle des ASCII 
Codes den EBCDIC Code, so wird dasselbe Bitmuster als ein anderer 
Buchstabe angezeigt. Es kann bei der Ausgabe wahlweise als Hex-, 
Dezimal-, Binär-, Oktal- oder zu jeder anderen beliebigen Basis 
ausgegeben werden. Das Bitmuster kann als Codierung augefasst werden, 
welche Lämpchen aufleuchten sollen und welche nicht oder welche Relais 
ein bzw. aus sein sollen ....

Aber egal, wie dieses Bitmuster bei der Ausgabe interpretiert wird, im 
Rechner ist es immer nur dasselbe: eine Zahl gebildet aus dem 1-0 
Bitmuster von ein paar Bits (genaugenommen ist es im Rechner eigentlich 
nur ein Bitmuster. Selbst die Auffassung einer Zahl ist schon eine 
Interpretation dieses Bitmusters). Welche Bedeutung diese Bits haben, 
bestimmst du als Programmierer bzw. spätestens dann, wenn du das 
Bitmuster irgendwo zur Anzeige bringst.

> wie bekomme ich das nun
> hin, das als hexadezimal zeichen auszugeben

Wie wäre es erst einmal damit, ein C-Buch durchzuarbeiten?
Ungefähr in Kapitel 3 (von 60) werden dort die ersten Ausgabevarianten 
durchgesprochen, was man so alles mit dem Formatstring von printf 
anstellen kann und welches % Kürzel wofür steht.
Wenn du dich an Netzwerke heranwagst, solltest du diese Dinge eigentlich 
aus dem FF beherrschen.

von juppi (Gast)


Lesenswert?

> Wie wäre es erst einmal damit, ein C-Buch durchzuarbeiten?

Wozu? Wenn er oft genug fragt, hilfst du ihm schon.

von gast (Gast)


Lesenswert?

hab es jetzt gelöst, das Problem besteht nicht mehr. Ich verwende auch 
ein C-Buch, hab nur eben aufgrund des Zeitdrucks ein paar Kapitel 
übersprungen. Ich weiss natürlich das auf der Leitung nur Spannung 
an/aus (1,0) anliegt.  Trotzdem wurde bei Programmiersprachen ja 
sicherlich schon abstrahiert. Im Maschinenbau hat man leider nicht so 
viel mit Programmierung am Hut. Ich bedanke mich trotzdem für eure Mühe. 
Ein letztes noch, was ich leider nicht in meinen C-Buch gfunden habe und 
mir etwas unklar ist:

meiner Funktion readData übergebe ich ja den Puffer von recvfrom

den Speicherbereich für data hab ich über die malloc funktion 
realiesiert und als Größe buf gegeben


recvfrom(s,data,buf,...)

als Rückgabewert geb ich dann die Adresse von data an, zeigt ja auf den 
Speicherbereich des ersten Zeichens. Das problem war nur das ich da nur 
ein Zeichen zurückgegeben bekommen habe. Schreibe ich aber &data[1] 
werden alle eingelesenen Zeichen, abgesehen natürlich vom ersten 
zurückgegeben.

Übergebe ich aber malloc buf + 1 funktioniert das ganze mit &data und 
alle eingelesenen Zeichen werden zurückgegeben. Das finde ich irgendwie 
seltsam.

Naja hauptsache es geht, falls einer mir das besagte Problem doch noch 
erklären könnte, würde ich mich freuen - nur zum Verständnis, man will 
ja auch wissen warum das so geht wie es geht.

mfg, Markus

von Klaus W. (mfgkw)


Lesenswert?

1
malloc buf + 1
wird dir niemand kompilieren, also zurück zum Start!
Ich verstehe deine letzte Frage auch nach dreimaligem Lesen nicht
so recht. Kann an mir liegen, erfahrungsgemäß ist sie aber wohl
einfach zu unklar formuliert.

Wo bekommst du nur ein Zeichen?

Kann es sein, daß du irgendwo die Daten verwendest, ohne eine
abschließende 0 anzuhängen, aber dich auf die 0 verlässt?
Z.B. zur Ausgabe eines Strings, den du mit recv() oder
so etwas bekommen hast, wirst du in der Regel selbst die
terminierende 0 anhängen müssen, bevor du den String mit
puts(), printf() o.s.ä. verwenden kannst.
Dazu muss der Puffer natürlich auch groß genug sein, also
Länge der Nutzdaten + 1.

von Markus (Gast)


Lesenswert?

meine Problem ist das bei ersten Aufruf meiner Funktion alles 
funktioniert, ich bekomme die zwei Befelsbestätigungszeichen aus meiner 
Funktion zurück. Beim nächsten Aufruf bekomme ich nur das erste Zeichen 
zurück, obwohl 25 Zeichen anliegen. Das hab ich überprüft, indem ich mir 
einfach mal die byt Anzahl zurückgegeben habe. Ich kann es aber auch 
kompilieren. Gestern hat es auch noch funktioniert, heute nicht mehr. 
Ich versteh das einfach nicht.


char* readData(int buf)
{

SOCKADDR_IN remoteAddr;
int remoteAddrLen=sizeof(SOCKADDR_IN);
char *data=malloc(buf);

int byt=recvfrom(s,data,buf,0,(SOCKADDR*)&remoteAddr,&remoteAddrLen);


    if(byt==SOCKET_ERROR )

    {
    int a=closesocket(s) ;
    WSACleanup() ;
    static char er[]="NULL";
    return er;


    }
    else

    {
     if (byt == 0)
   {    static char xp[]="keine Daten";
        return xp;

    }
    else

       {

   // data[byt]='\0';
    //int len=strlen(data);
    //char *xa=malloc(byt+1);

    //strcpy(xa,data);
    data[byt]='\0';
    return data;//&data;
}
    }

}

von Markus (Gast)


Lesenswert?

jetzt hab ich zurückgegeben einfach mal &data[2] der erhalte ich auf 
einmal wieder alle daten bis auf die ersten 2

von Klaus W. (mfgkw)


Lesenswert?

Wenn der Quelltext vernünftig formatiert wäre, könnte man ihn auch 
lesen...

von Klaus W. (mfgkw)


Lesenswert?

Wer gibt eigentlich den Speicher im Fehlerfall frei?

von Klaus W. (mfgkw)


Lesenswert?

Wenn du maximal buf Zeichen liest, musst du buf+1 Zeichen allokieren, um 
Platz für die abschließende 0 zu haben.

von Markus (Gast)


Lesenswert?

In buf übergebe ich 100 Zeichen in einer Endlosschleife. 25<100 -> 
müsste ja alles okay sein . Hab trotzdem einmal probiert buf +1 an die 
malloc-Funktion zu übergeben. Dies hat leider keine Besserung gebracht. 
Nur wenn ich die 3 Adresse übergebe sehe ich alle restlichen Daten. Aber 
ich brauche natürlich auch die Daten von der Adresse 1 und 2

von Markus (Gast)


Lesenswert?

bei data[1] erhalte ich einen Leerstring, vielleicht ist das ja das 
Problem. Auf dieser Adresse befindet sich keine Zeichen (auch kein 
Leerzeichen oder was ähnliches)

von Klaus W. (mfgkw)


Lesenswert?

data[1] ist kein String, sondern ein Zeichen.

von Markus (Gast)


Lesenswert?

ja ich weiss, aber da befindet sich eben kein Zeichen

von Peter (Gast)


Lesenswert?

> ja ich weiss, aber da befindet sich eben kein Zeichen
doch ist es, jedes element in den daten ist ein zeichen, auch wenn kein 
darstellbares. Lass dir das ganze doch mal als Hex ausgeben.

von Klaus W. (mfgkw)


Lesenswert?

kleiner Tip:
Bevor ich mich mit Netzwerk herum ärgere, würde ich vielleicht erstmal
die Grundlagen von C lernen.

Und bei vernünftigen Fragen (ordentlich beschrieben, lesbarer Quelltext)
bekommt man auch leichter vernünftige Fragen. So macht es wenig Spaß.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
>     else
>
>        {
>
>    // data[byt]='\0';
>     //int len=strlen(data);
>     //char *xa=malloc(byt+1);
>
>     //strcpy(xa,data);
>     data[byt]='\0';
>     return data;//&data;
> }
>     }
>
> }

Du hast es immer noch nicht.
Lies es von meinen Lippen ab:
Auf dieser Ebene hast du keine Strings mehr! Hier gibt es nur noch 
Bytes, keine Strings. Damit aus einer Abfolge von Bytes in C ein String 
wird, müssen ein paar wichtige Regeln eingehalten werden! Eine davon 
ist: Sobald ein 0-Byte auftaucht, ist der String zu Ende!

Daher ist die Verwendung von Stringfunktionen auf dieser Ebene absolut 
kontraproduktiv. Vor allem dann, wenn dir dein Messgerät keine Texte 
sondern einfach nur eine Bytefolge schickt. Niemand garantiert dir, dass 
in so einer Bytefolge nicht ein 0-Byte enthalten ist. Es ist sogar sehr 
wahrscheinlich, dass dem so ist.

Um mit Bytes zu arbeiten gibt es die Familie der mem... Funktionen. 
Vergiss str... an dieser Stelle. Das führt dich immer wieder in eine 
Sackgasse.

Und nochwas: Wenn du mit Bytes arbeitest, dann ist der Datentyp der Wahl 
'unsigned char' und keinesfalls 'char'. Das öffnet nämlich den nächsten 
Sack an Problemen.

von Karl H. (kbuchegg)


Lesenswert?

> Ich verwende auch
> ein C-Buch, hab nur eben aufgrund des Zeitdrucks ein paar Kapitel
> übersprungen.

Das ist keine gute Ausrede. Du hast ja auch noch die Nachtstunden

von Markus (Gast)


Lesenswert?

auf der Adresse von data[1] steht 0 drin

von Karl H. (kbuchegg)


Lesenswert?

> ja du hast recht, mein Messgerät schickt zuerst ein Byte, welches die
> Anzahl der nächsten dazugehörigen Bytes beschreibt.

Schickt das Messgerät auch noch ein eindeutiges Byte, wenn ein Datensatz 
zu Ende ist?
Das wäre wichtig, damit man die Kommunikation wieder synchronisieren 
kann, falls aus irgendeinem Grund Sender und Empfänger asynchron werden.

Deine Empfangsfunktion müsste in etwa so aussehen
1
unsigned char * readData()
2
{
3
  SOCKADDR_IN remoteAddr;
4
  int remoteAddrLen = sizeof( remoteAddr );
5
  int bytesReceived = 0;
6
  int totalBytesReceived = 0;
7
  int expectedBytes = 0;
8
  unsigned char data[256];  // kann nicht größer sein, da die
9
                              //  gesendete Längenangabe 1 Byte ist.
10
  unsigned char * returnData;
11
  
12
  bytesReceived = recvfrom( s, data, sizeof(data), 0,
13
                           (SOCKADDR*)&remoteAddr, &remoteAddrLen );
14
15
  // das erste empfangene Byte gibt die Länge des Datensatzes an
16
  expectedBytes = data[0];
17
  bytesReceived--;
18
19
  returnData = malloc( expectedBytes + 1 );  // nur um sicher zu gehen
20
                                             // 1 mehr und dann zum
21
                                             // Schluss noch ein \0 rein
22
23
  //
24
  // aus dem empfangenen ersten Paket erst mal alles
25
  // auf die Seite bringen was da ist
26
  //
27
  memcpy( returnData, &data[1], bytesReceived );
28
  totalBytesReceived = bytesReceived;
29
30
  //
31
  // warte jetzt auf den Rest der noch fehlt
32
  //
33
  while( totalBytesReceived < expectedBytes ) {
34
    bytesReceived = recvfrom( s, data, sizeof(data), 0,
35
                              (SOCKADDR*)&remoteAddr, &remoteAddrLen );
36
37
    // Noch Daten eingetrudelt?
38
    if( bytesReceived > 0 ) {
39
      // die neuen Daten an das bisher Empfangene anhängen
40
      memcpy( &returnData[ totalBytesReceived ],
41
              data,
42
              bytesReceived );
43
      // und damit sind wir dem Endziel, nämlich expectedBytes Bytes
44
      // zu empfangen, wieder ein Stückchen näher
45
      totalBytesReceived += bytesReceived;
46
    }
47
    else if( bytesReceived == SOCKET_ERROR ) {
48
      free( returnData );
49
      return NULL;
50
    }
51
  }
52
53
  // Das wars. Die Anzahl der erwarteten Bytes ist da
54
  // Zur Sicherheit, wenn es ein String ist, noch hinten
55
  // eine 0 anhängen.
56
  // Wenn die Daten Binärdaten sind, darf das nicht passieren!
57
  returnData[ expectedBytes ] = '\0';
58
  return returnData;
59
}

Achtung: Ich habe den Code nicht getestet sondern blind geschrieben. Er 
sollte zumindest dicht drann sein. Am besten im Debugger durchsteppen 
und sich alle Variablen ansehen und was da so alles passiert.

Um Fehlerbehandlung musst du dich auch noch kümmern.
Was aber auf keinen Fall sein kann: Dass mir eine readData Funktion den 
socket schliesst. Das ist nicht ihre Aufgabe! Die Funktion soll Daten 
empfangen. Wenn es dabei ein Problem gibt, soll sie das melden. Aber 
ansonsten soll sie die Finger vom Socket lassen.

Mit dem malloc da drinnen bin ich absolut unglücklich. Ist nur wieder 
ein Stolperstein, dass der Aufrufer den free vergisst.
Besser wäre es, wenn deine Funktion so aussehen würde
1
int readData( unsigned char * recBuffer, size_t bufferLen )
2
{
3
   ...
4
}

Die Funktion readData kriegt einen Buffer (der gross genug sein muss, 
Längenangabe in bufferLen) in dem sie die Daten abzuliefern hat. Als 
Returnwert liefert sie die Anzahl der Bytes, welche sie in den Buffer 
gestellt hat.

von Markus (Gast)


Lesenswert?

ja danke, das ist ein sehr guter Anhaltspunkt.

von Karl H. (kbuchegg)


Lesenswert?

Markus schrieb:
> ja danke, das ist ein sehr guter Anhaltspunkt.

Diese Funktion ist noch nicht einmal ansatzweise dort, wo sie eigentlich 
sein müsste.

Wenn dein Messgerät mehrere Antworten in kurzer Folge hintereinander 
schickt, dann wird das Probleme geben. Da müsste man noch eine FIFO 
dazwischen schalten, die den überschüssigen Anteil nach den jeweiligen 
recvfrom aufnimmt. Und die readData müsste als allererstes in diese FIFO 
schauen um zu sehen, ob da noch nicht verarbeitete Bytes rumlungern und 
sich zuerst von diesen bedienen, ehe sie mittels recvfrom die FIFO 
wieder füllt.
Und aus genau dem gleichen Grund können die memcpy kräftig in die Hose 
gehen.

von Karl H. (kbuchegg)


Lesenswert?

Stell dir einfach vor, aus dem ersten recvfrom kommt diese Bytefolge 
raus

  0x05 0x10 0x20 0x30 0x40 0x50 0x08 0x10 0x20

und dann gehst du am Papier die Funktion durch.
Hinweis: In dieser Bytefolge sind 2 Antworten vom Messgerät enthalten! 
Die erste (mit einer Länge von 5) ist komplett, die zweite (mit einer 
Länge von 8) ist noch nicht komplett.

Trotzdem müssen beide Antworten bei 2 Aufrufen von readData korrekt 
entschlüsselt und richtig aufgeteilt werden.

Bei solchen Sachen ist überhaupt Papierarbeit sehr wichtig! Vor allem 
wenn man das noch nie gemacht hat! Es bringt nichts, da auf gut Glück 
den Code zu verändern. Du brauchst reproduzierbare Verhältnisse und du 
musst dir über jede einzelne Anweisung im klaren sein was sie macht, 
warum sie da ist und was ihre Aufgabe ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.