TCP/IP Socket Prgrammierung-Probleme beim Senden/empfangen

Gast #4241503
Lesenswert?

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:
1
ctr=malloc(sizeof(int));
2
if((recv(IDMySocket, ctr, 1,0))!=0)
3
printf("%d\n",ctr);
4
free(ctr);
Gast #4241508
Lesenswert?

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...
Gast #4241546
Lesenswert?

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.
Gast #4241547
Lesenswert?

Ich benutze ein Beaglebone black, mit Neutrino RTOS Betriebssytem.

Mein Sendeteil sieht so aus:
1
if(send(IDclient,&ADCbuffer[n],1,0)!=-1)
2
printf("Sende Signal:%d\n",ADCbuffer[n]);

ADCbuffer ist ein uint32_t Array. In dem Fall schicke ich eine "1".
Erhalte eine "134529632".
Gast #4241565
Lesenswert?

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.
Persönliche Seite #4241624
Lesenswert?

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.
#4241627
Lesenswert?

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
#4241665
Lesenswert?

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
Gast #4242190
Lesenswert?

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.
Gast #4242294
Lesenswert?

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!
#4242309
Lesenswert?

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.
Gast #4242530
Lesenswert?

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.
#4242620
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren