Hi,
ich habe ein Programm, das über TCP/IP Protokoll eine Zahl schickt und
der Client empfängt diese.
Nur ist mein Problem, dass die Zahl, die der Client ganz und gar nichts
mir der ursprünglichen zu tun hat.
Der Client Code-Ausschnitt sieht so aus:
Gehts auch genauer?
Welches Betriebssystem?
Was schickst du, und was empfängst du?
Hast du an Netzwerk-Byteorder gedacht?
Sorry, aber bei meiner Glaskugel ist der Akku grad alle.
Ansonsten ist dein Fehler in Zeile 42 zu finden...
Ein gerne gemachter Fehler bei recv() ist anzunehmen das in einem Aufruf
alle Bytes ankommen. Man muss aber in einer Schleife solange Bytes
sammeln bis ist=sollanzhl ist oder recv() einen Fehler oder anz=0 =>
Verbindungsabbruch meldet.
Das Size steht schon für die Sollanzahl, aber es ist nicht garantiert
das die Daten tatsächlich in einem Rutsch kommen. Gilt hauptsächlich für
non-blocking sockets, aber auch bei blocking muss man mit Fehlern oder
Verbindungsabbruch rechnen. Und TCP vorausgesetzt.
QX schrieb:> Der Client Code-Ausschnitt sieht so aus:> ctr=malloc(sizeof(int));> if((recv(IDMySocket, ctr, 1,0))!=0)> printf("%d\n",ctr);> free(ctr);
ctr ist also ein Pointer.
Mit Deiner printf-Anweisung gibst Du aber nicht das aus, worauf der
Pointer zeigt, sondern den Pointer selbst.
Lies Dir mal in Deinem C-Buch das Kapitel über Pointer und deren
Dereferenzierung durch.
QX schrieb:> ctr=malloc(sizeof(int));> if((recv(IDMySocket, ctr, 1,0))!=0)> printf("%d\n",ctr);> free(ctr);
Dein printf sieht komisch aus... ctr ist ein Pointer auf einen Integer.
Der hat mindestens 2 Byte, du empfängst hier aber nur ein Byte! Damit
ist schonmal mindestens die Hälfte deines ctr undefiniert. Außerdem
müsste im printf *ctr stehen, weil du ja nicht den Pointer, sondern den
Wert auf den er zeigt ausgeben willst!
Gruß
Marius
Jojo S. schrieb:> Das Size steht schon für die Sollanzahl
Nicht wirklich. Das steht eigentlich für die Buffergröße, also die
Maximalanzahl von Bytes, die recv da reinschreiben darf.
Steht ja auch explizit so in dem von Kaj geposteten Screenshot
OK,
1. Du sendest einzeln die Werte aus einem uint32_t Array. Das sind in
jedem Fall unsigned ints mit 32 Bit, also 4 Byte pro Wert
2. beim senden gibst Du als größe aber nur 1 Byte an
3. Du beachtest die Byte-Order nicht, ich kenne das Beagleboard nicht
und ich kenne den Empfänger nicht, ist die bei beiden gleich?
4. Du versucht in einen signed int zu lesen den Du dynamisch allokierst
5. auch beim lesen gibst Du nur eine Größe von 1 Byte an
6. Du gibst im printf nicht den Wert aus den der int Zeiger enthält,
sondern nur den Zeiger, erhält also dessen Adresse als Ausgabe
Wenn Du weiter einzelne Werte senden willst:
a) Wandle das zu sendende Wort mit hton in die Netzwerkdarstellung um
b) sende genügend Bytes z.B. mit
send(IDclient,&ADCbuffer[n],1*sizeof(uint32_t),0)
c) verwende den richtigen Datentyp uint32_t* Car =
malloc(sizeof(uint32_t));
d) Lese auch genügend Bytes mit recv(IDMySocket, ctr,
1*sizeof(uint32_t),0)
e) wandle das gelesene wieder in die Host Darstellung um: *ctr =
ntoh(*ctr)
f) referenzierten den Zeiger zur Ausgabe: *ctr und nicht nur *ctr im
printf
zu allen Funktionen gibt es im Netz genügend Infos und Beispiele!
Es ist richtig das die Datenpakete von den TCP/IP Stacks nicht unbedingt
am Stück gesendet oder empfangen werden müssen. Aber wenn die Pakete
klein genug sind, nicht irgendwo fragmentiert werden und NAGLE nicht
abgeschaltet wurde, dann ist es doch sehr wahrscheinlich, dass das an
Bytes ankommt, was auch gesendet wurde. Wenn Du mit deinem einen Wert
klar kommst und größere Pakete senden willst, dann kannst Du immer noch
weiter sehen….
Gruß Martin
Martin K. schrieb:> d) Lese auch genügend Bytes mit recv(IDMySocket, ctr,> 1*sizeof(uint32_t),0)
Und überprüfe ob auch tatsächlich 1*sizeof(uint32_t) Bytes gelesen
wurden!
Jojo S. schrieb:> Das Size steht schon für die Sollanzahl, aber es ist nicht garantiert> das die Daten tatsächlich in einem Rutsch kommen. Gilt hauptsächlich für> non-blocking sockets, aber auch bei blocking muss man mit Fehlern oder> Verbindungsabbruch rechnen. Und TCP vorausgesetzt.
Das hat nichts mit Fehlern oder Verbindungsabbrüchen zu tun. Es wird das
zurückgeliefert, was verfügbar ist. Das muß auch bei normaler Verbindung
nicht unbedingt soviel sein, wie man als Size angegeben hat. Es muß auch
nicht soviel sein, wie der Sender am Stück an seine send-Funktion
übergeben hat.
Deshalb muß man bei solchen Syscalls wie recv oder read eigentlich in
einer Schleife so lange lesen, bis man die gewünschte Datenmenge
erhalten hat. Und man muss auf Fehler prüfen, denn nicht jede Fehler
bedeutet kompletten Abbruch, sondern manch einer erfordert einfach einen
erneuten Leseversuch.
QX schrieb:> ctr=malloc(sizeof(int));
Warum allokierst du den int denn dynamisch?
Martin K. schrieb:> Es ist richtig das die Datenpakete von den TCP/IP Stacks nicht unbedingt> am Stück gesendet oder empfangen werden müssen. Aber wenn die Pakete> klein genug sind, nicht irgendwo fragmentiert werden und NAGLE nicht> abgeschaltet wurde, dann ist es doch sehr wahrscheinlich, dass das an> Bytes ankommt, was auch gesendet wurde.
Ja, wenn x und wenn y und wenn z, dann geht's wahrscheinlich...
Und nächste Woche kommt die nächste Frage, warum's nicht mehr klappt,
wenn er größere Pakete sendet.
Martin K. schrieb:> Es ist richtig das die Datenpakete von den TCP/IP Stacks nicht unbedingt> am Stück gesendet oder empfangen werden müssen. Aber wenn die Pakete> klein genug sind, nicht irgendwo fragmentiert werden und NAGLE nicht> abgeschaltet wurde, dann ist es doch sehr wahrscheinlich, dass das an> Bytes ankommt, was auch gesendet wurde.
Ja super Aussage, leider unbrauchbar!
Wir haben mal Wochen einen selten auftauchenden Fehler in einer
selbstgeschriebenen recht umfangreichen Mittelware gesucht, bis wir
durch Codeanalyse das tatsächliche Problem gefunden hatten. Ursache war,
dass in der untersten Ebene erst ein 2 Byte Wert für die Größe des
nachfolgenden Datenblocks und dann die Daten selbst gesendet und
empfangen wurden.
Der Empfänger hat zwar schön in einer Schleife die Daten
zusammengesammelt, aber bei der 2Byte Länge ist er davon ausgegangen,
dass die ja in einem Rutsch kommt. Klar aber nur bei 99,995% aller
Fälle.
Merke: Man kann sich NIE NIE NIE sicher sein, dass man alle Bytes auf
einmal empfängt!
Der Andere schrieb:> Martin K. schrieb:>> Aber wenn die Pakete>> klein genug sind, nicht irgendwo fragmentiert werden und NAGLE nicht>> abgeschaltet wurde, dann ist es doch sehr wahrscheinlich, dass das an>> Bytes ankommt, was auch gesendet wurde.>> ....>> Merke: Man kann sich NIE NIE NIE sicher sein, dass man alle Bytes auf> einmal empfängt!
Oder auf Deutsch: machs gleich richtig, dann hast du weniger Probleme,
die dich beissen können.
Jede windige Annahme, die man erst mal akzeptiert, gerät im laufe der
Zeit in Vergessenheit und wartet nur darauf zuzuschlagen. Natürlich
dann, wenn sie maximalen Schaden anrichten kann.
Karl H. schrieb:> Jede windige Annahme, die man erst mal akzeptiert, gerät im laufe der> Zeit in Vergessenheit und wartet nur darauf zuzuschlagen. Natürlich> dann, wenn sie maximalen Schaden anrichten kann.
Jepp, ich habe schon einige Arbeitszeit damit verbraten solche
Zeitbomben zu finden. Eigene und noch öfter die von anderen.
Karl H. schrieb:> Der Andere schrieb:>> Martin K. schrieb:>>> Aber wenn die Pakete>>> klein genug sind, nicht irgendwo fragmentiert werden und NAGLE nicht>>> abgeschaltet wurde, dann ist es doch sehr wahrscheinlich, dass das an>>> Bytes ankommt, was auch gesendet wurde.>>>> ....>>>> Merke: Man kann sich NIE NIE NIE sicher sein, dass man alle Bytes auf>> einmal empfängt!>> Oder auf Deutsch: machs gleich richtig, dann hast du weniger Probleme,> die dich beissen können.> Jede windige Annahme, die man erst mal akzeptiert, gerät im laufe der> Zeit in Vergessenheit und wartet nur darauf zuzuschlagen. Natürlich> dann, wenn sie maximalen Schaden anrichten kann.
Ja, aber: Meint Ihr das jemand der in gerade einmal einem halben Dutzend
Code Zeilen so mit Datentypen und Zeigern und unsigned oder nicht und
Pointer oder nicht um sich wirft das hin bekommt? Es gibt ja immer noch
die TODO Kommentare - die natürlich auch zeitnah bearbeitet werden
müssen ;-)
Gruß Martin