Netzwerkprogrammierung: Übertragen von 0x00 über send/recv?

ENNEMMEE

Member
Ja, ich mal wieder mit meinen Noob-Problemen ;)

Jemand ne Ahnung wie ich mit den c-Netzwerk-Funktionen send(...) und recv(...) auch das Terminierungszeichen auswertbar übertragen kann?
Möchte zum Beispiel Zahlenwerte senden - aber nicht als Klartext, sondern als Zahl...

Beispiel:

Die Zahl 436253891 möchte ich nicht als Zeichenkette "436253891" schicken sondern als Hexwert, sprich 0x1A00B4C3

Da sowohl send(...) als auch recv(...) auf char-Arrays basieren wird ab dem Nullzeichen (also 0x00) abgeschnitten und es kommt folgerichtig nur 0x1A an, anstatt 0x1A00B4C3

Ein RawSocket wäre eine Lösung, aber soweit ich das bis jetzt nachgelesen habe, sind für die Erstellung von RawSockets root-Rechte notwendig :(

Ich vermute das Problem tritt nicht erst beim Empfangen auf, sondern schon beim Senden, da nach dem Auslesen der (unvollständigen) aus dem Empfangspuffer auch keine weiteren Daten mehr auf dem Empfangspuffer liegen :grumble:

Wäre sehr schön, wenn mir jemand bei meinem "Problemchen" weiterhelfen könnte... alles was mir dazu einfällt, wäre eine Aufteilung des char-Arrays an den Stellen, wo das Null-Zeichen auftritt - allerdings brauch ich dann eine verlässliche Methode zu erkennen, dass ein Nullzeichen beim Empfänger eingefügt werden muss...

Vielen Dank schon mal im Vorraus für die Hilfe :D
 
ENNEMMEE schrieb:
Da sowohl send(...) als auch recv(...) auf char-Arrays basieren wird ab dem Nullzeichen (also 0x00) abgeschnitten
Diese Aussage ist falsch. Wenn Du die Pufferlänge korrekt mitgibst, dann arbeitet sowohl send/recv als auch read/write mit Bytes des Wertes Null. In Deinem Falle sollte die Pufferlänge VIER (4) sein. Überprüfe das mal. Haste nicht *doch* ein strlen() zum ermitteln der Pufferlänge verwendet? Kann ja sein .... :rolleyes:
BTW: Ich hab mal gelesen, man solle bei der Netzwerkprogrammierung eigentlich immer ASCII Text verwenden, und nicht so gerne Binärdaten, weil man es dann leichter hat das zu sniffen und zu debuggen. Verwende mal etherreal / tcpdump um rauszufinden was wirklich über die Verbingung läuft.
 
Da sowohl send(...) als auch recv(...) auf char-Arrays basieren wird ab dem Nullzeichen (also 0x00) abgeschnitten und es kommt folgerichtig nur 0x1A an, anstatt 0x1A00B4C3

Seit wann das? In der man-page von send steht
Code:
ssize_t send (int s, const void *msg, size_t len, int flags);
und ich kann mich auch nicht daran erinnern jemals damit Probleme gehabt zu haben. Was Du suchst ist wahrscheinlich:
Code:
unsigned long l = htonl(436253891);
if ( sizeof(long) != send(s, (void*)&l, sizeof(long), 0 ) )
{
  // fehler
}
.
 
Jo... Als Länge wird in obigem Beispiel 4 übereben... im Code hab ich als Test-Zeichenkette "Mess\0age" verwendet... bekomme aber auf der Seite des recv(...) als Ergebnis nur "Mess", auch wenn ich per for-Schleife alle Zeichen abgehe... recv(...) gibt interessanterweise ja auch 8 gelesene Zeichen zurück...

Aber naja, wenn ihr sagt, dass send(...) und recv(...) sich da eigentlich anders verhalten und das schon funktionieren sollte, dann muss der Fehler ja mal wieder definitiv bei mir liegen... mal weitersuchen... oder gleich neu coden :D

Danke nochmal!
 
ENNEMMEE schrieb:
... recv(...) gibt interessanterweise ja auch 8 gelesene Zeichen zurück...
Na also, dann hast Du auch die 8 Bytes bekommen. Möglicherweise gibst Du das dann per printf("%s", puffer) aus. Dann hast Du verloren. Da bekommst Du nur "Mess". Geb mal den Puffer beispielsweise so aus:
Code:
for (i=0; i<gelesenebytes; i++)
        printf("Byte %d = %02X\n", i, (int)puffer[i]);
Ich trau mich wetten, dass Du dann Dein Nullbyte siehst.
Tip: Bevor Du mit Netzwerkprogrammierung startest, solltest Du vielleicht in der "normalen" C-Programmierung sattelfester werden.
 
ENNEMMEE schrieb:
bekomme aber auf der Seite des recv(...) als Ergebnis nur "Mess", auch wenn ich per for-Schleife alle Zeichen abgehe...

Ich dachte ich hatte es bereits erwähnt ;)

Zum Thema C... muss zugeben, es is ne Weile her und ich hab mich eigentlich nur noch mit C++ befasst... von daher bin ich schon ein wenig eingerostet, was C betrifft... wie gesagt... ne ganze Weile her... aber als Hilfesuchender geh ich einfach in Foren, da erhofft man sich in der Regel auch Hilfe... :D
 
Du bekommst also von recv einen Puffer, von dem man aufgrund des Returnwertes von recv sagen kann, das er mit 8 Bytes gefüllt ist. Gut.

puffer[0] ist 'M' oder 0x4D
puffer[1] ist 'e' oder 0x65
puffer[2] ist 's' oder 0x73
puffer[3] ist 's' oder 0x73

Was steht an puffer[4] ?? Irdendwas muss da stehen, denn recv hat Dir 8 Bytes gegeben. D.h. der puffer ist von puffer[0] bis puffer[7] mit Werten gefüllt, die von der Gegenstelle kommen.
Du darfst weder
Code:
printf("%s", puffer);
noch
Code:
printf("%c", puffer[4]);
machen. Zur Ausgabe eines Bytes mit dem Wert 0x00 musst Du
Code:
printf("%02X", (int)puffer[4]);
anwenden. Weil Dein Terminal das Zeichen mit dem Dezimalwert 0x00 nicht als '0' darstellt. '0' hat den Wert 0x30.

OK?
 
Die übrigen Zeichen sind allesamt 0x00... wobei ich jetz ein sehr interessantes Phänomen hab: auf meiner alten FreeBSD4-Kiste funktioniert alles tadellos... auf meinem FreeBSD5 hab ich besagten Fehler... daraufhin hab ich auch mal andere Maschinen getestet und siehe da: dort geht es überall... es liegt irgendwie an meiner FreeBSD5-Kiste :confused: Aber gut, die wollte ich sowieso mal wieder neu aufsetzen... :D
 
d-ra schrieb:
BTW: Ich hab mal gelesen, man solle bei der Netzwerkprogrammierung eigentlich immer ASCII Text verwenden, und nicht so gerne Binärdaten, weil man es dann leichter hat das zu sniffen und zu debuggen. Verwende mal etherreal / tcpdump um rauszufinden was wirklich über die Verbingung läuft.

Unbedingt nur char's benutzen, da es sonst zu unschönen Vorkommnissen kommen kann: eine Maschine kann mit BIGENDIAN laufen, die andere mit LITTLENDIAN usw... nicht das man sowas nicht lösen (= konvertieren) könnte, aber es erspart ne Menge "unnötige" Arbeit ;)
 
Cédric schrieb:
Unbedingt nur char's benutzen, da es sonst zu unschönen Vorkommnissen kommen kann: eine Maschine kann mit BIGENDIAN laufen, die andere mit LITTLENDIAN usw... nicht das man sowas nicht lösen (= konvertieren) könnte, aber es erspart ne Menge "unnötige" Arbeit ;)

Genau dafür gibt es doch ntohl()/htonl() resp. ntohs()/htons()... Man muss sich nur angewöhnen die auch immer zu benutzen...
 
@Cédric: Danke für die Antwort. Ja genau so habe ich es auch mal gelesen. Die ganzen Protokolle im Internet laufen ja auch mit ASCII-Text. Und immer schön eine Zeile mit "\r\n" beenden (nicht nur mit "\n").
 
Zurück
Oben