www.mikrocontroller.net

Forum: PC-Programmierung Problem mit winsock


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCP oder UDP?

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: JojoS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
  unsigned char SendBuffer[10];

  SendBuffer[0] = 0x12;
  SendBuffer[1] = 0x78;
  SendBuffer[2] = 'd';
  SendBuffer[3] = 'e';

  sendto( serverSocket, SendBuffer, 4, ...

  //
  // oder:
  // sendto( serverSocket, (char*)SendBuffer, 4, ...


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: juppi (Gast)
Datum:

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

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

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}
    }

}

Autor: Markus (Gast)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wer gibt eigentlich den Speicher im Fehlerfall frei?

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
data[1] ist kein String, sondern ein Zeichen.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja ich weiss, aber da befindet sich eben kein Zeichen

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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ß.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
auf der Adresse von data[1] steht 0 drin

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
unsigned char * readData()
{
  SOCKADDR_IN remoteAddr;
  int remoteAddrLen = sizeof( remoteAddr );
  int bytesReceived = 0;
  int totalBytesReceived = 0;
  int expectedBytes = 0;
  unsigned char data[256];  // kann nicht größer sein, da die
                              //  gesendete Längenangabe 1 Byte ist.
  unsigned char * returnData;
  
  bytesReceived = recvfrom( s, data, sizeof(data), 0,
                           (SOCKADDR*)&remoteAddr, &remoteAddrLen );

  // das erste empfangene Byte gibt die Länge des Datensatzes an
  expectedBytes = data[0];
  bytesReceived--;

  returnData = malloc( expectedBytes + 1 );  // nur um sicher zu gehen
                                             // 1 mehr und dann zum
                                             // Schluss noch ein \0 rein

  //
  // aus dem empfangenen ersten Paket erst mal alles
  // auf die Seite bringen was da ist
  //
  memcpy( returnData, &data[1], bytesReceived );
  totalBytesReceived = bytesReceived;

  //
  // warte jetzt auf den Rest der noch fehlt
  //
  while( totalBytesReceived < expectedBytes ) {
    bytesReceived = recvfrom( s, data, sizeof(data), 0,
                              (SOCKADDR*)&remoteAddr, &remoteAddrLen );

    // Noch Daten eingetrudelt?
    if( bytesReceived > 0 ) {
      // die neuen Daten an das bisher Empfangene anhängen
      memcpy( &returnData[ totalBytesReceived ],
              data,
              bytesReceived );
      // und damit sind wir dem Endziel, nämlich expectedBytes Bytes
      // zu empfangen, wieder ein Stückchen näher
      totalBytesReceived += bytesReceived;
    }
    else if( bytesReceived == SOCKET_ERROR ) {
      free( returnData );
      return NULL;
    }
  }

  // Das wars. Die Anzahl der erwarteten Bytes ist da
  // Zur Sicherheit, wenn es ein String ist, noch hinten
  // eine 0 anhängen.
  // Wenn die Daten Binärdaten sind, darf das nicht passieren!
  returnData[ expectedBytes ] = '\0';
  return returnData;
}

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
int readData( unsigned char * recBuffer, size_t bufferLen )
{
   ...
}

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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja danke, das ist ein sehr guter Anhaltspunkt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.