Forum: Compiler & IDEs Binäre Übertragung über Ethernet


von Cassidy (Gast)


Lesenswert?

Hallo,

Ich programmiere zur Zeit einen Atmega328p mit einem W5100 Wiznet Chip 
für die Ethernet Schnittstelle. Diese beiden kommunizieren über eine SPI 
Schnittstelle.

Die Implementierung hat uach wunderbar geklappt, Verbindungsaufbau / 
-abbau, senden und empfangen klappt soweit.

Jetzt habe ich die Aufgabe bekommen, Daten nach einem bestimmten 
Anwendungsprotokoll zu senden und zu empfangen:

Anfrage:
|NachrichtenLänge|NachrichtenTyp|anzSamples|16x bool Kanäle|
|uint32|uint16|uint32|uint16|

Antwort:
|NachrichtenLänge|NachrichtenTyp| chan  sample  anz|
|uint32|uint16|chan  anz  double|


Mein Empfangsbefehl fürs Ethernet:
ETH_recv(uint8_t *buf,uint16_t len);


Problem:
Ich habe probleme beim Einlesen der Request Anfrage.

ms_len = ((unsigned long) buf[0] << 24)
       + ((unsigned long) buf[1] << 16)
       + ((unsigned long) buf[2] << 8)
       + ((unsigned long) buf[3]);
uint16_t ms_typ = ((unsigned short) buf[4] << 8)                + 
((unsigned short) buf[5]);

Diese Methode habe ich versucht, aber erhalte ich keine 
Nachvollziehbaren Daten.
Kann mir jemand helfen, wie ich dieses Problem am besten realisieren 
kann oder wo mein Denkfehler liegt?

Grüße Cassidy

von Karl H. (kbuchegg)


Lesenswert?

Cassidy schrieb:

> Problem:
> Ich habe probleme beim Einlesen der Request Anfrage.
>
> ms_len = ((unsigned long) buf[0] << 24)
>        + ((unsigned long) buf[1] << 16)
>        + ((unsigned long) buf[2] << 8)
>        + ((unsigned long) buf[3]);
> uint16_t ms_typ = ((unsigned short) buf[4] << 8)                +
> ((unsigned short) buf[5]);

Dir ist aber schon klar, dass du hier allerhand Annahmen über die 
Bytereihenfolge triffst?
zb das das höherwertigste Byte zuerst im Datenstrom kommt.

Das muss aber nicht so sein. Das hängt unter anderem auch davon ab, wie 
der Sender die Daten auf den Weg bringt.

> Diese Methode habe ich versucht, aber erhalte ich keine
> Nachvollziehbaren Daten.

Hast du dir schon mal die Einzelbytes angesehen?
Also: Noch ehe du sie zu größeren Einheiten zusammensetzt.

von Karl H. (kbuchegg)


Lesenswert?

Cassidy schrieb:

> Kann mir jemand helfen, wie ich dieses Problem am besten realisieren
> kann

Bei solchen Problemen fängt man immer damit an, dass man sich zuerst auf 
tifster Ebene erst mal die Bytes ansieht, die aus einer Verbindung 
herauspurzeln und sich ansieht, ob die plausibel und richtig sein 
können. Und zwar sieht man sich die Bytes so an, wie sie ankommen: Als 
Bytes.

Stimmen die schon nicht, ist es sinnlos auf höheren Ebenen nach Fehlern 
zu suchen.

von Cassidy (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Dir ist aber schon klar, dass du hier allerhand Annahmen über die
> Bytereihenfolge triffst?
> zb das das höherwertigste Byte zuerst im Datenstrom kommt.
>
> Das muss aber nicht so sein. Das hängt unter anderem auch davon ab, wie
> der Sender die Daten auf den Weg bringt.
>
>> Diese Methode habe ich versucht, aber erhalte ich keine
>> Nachvollziehbaren Daten.
>
> Hast du dir schon mal die Einzelbytes angesehen?
> Also: Noch ehe du sie zu größeren Einheiten zusammensetzt.

Also Ich hatte vorher ein Programm, welches Zeichenketten (mit 
Trennzeichen) gesendet hat,
dort kamen die Zeichen geordnet an und es konnte alles richtig 
interpretiert werden.

Deshalb gehe ich davon aus, dass meine Bytes die übertragen werden 
ebenso geordnet ankommen, da ich meine Bytes ja als Chars übertrage.
Vielleicht habe ich auch gerade einen Denkfehler, oder übersehe etwas, 
da ich in dem Bereich der Programmierung noch recht neu bin.


Könnte es sein, dass meine 0-Bytes den Datenstrom terminieren, da ich ja 
über char-arrays sende? Und wenn ja, welche möglichkeit habe ich, das zu 
unterbinden?

Grüße Cassidy

von Karl H. (kbuchegg)


Lesenswert?

Cassidy schrieb:

>> Hast du dir schon mal die Einzelbytes angesehen?
>> Also: Noch ehe du sie zu größeren Einheiten zusammensetzt.
>
> Also Ich hatte vorher ein Programm, welches Zeichenketten (mit
> Trennzeichen) gesendet hat,
> dort kamen die Zeichen geordnet an und es konnte alles richtig
> interpretiert werden.

Zeichenketten sind uninteresant für diesen konkreten Fall.

> Deshalb gehe ich davon aus, dass meine Bytes die übertragen werden
> ebenso geordnet ankommen, da ich meine Bytes ja als Chars übertrage.

Das ist nicht die Frage.

Nehmen wir 2 Byte Zahlen.
zb die Zahl 23598
die interne Repräsentierung dieser Zahl ist  0x5C2E

sie bestehst aus 2 Byte.
Aber das bedeute nicht, dass diese Bytes in dieser Reihenfolge auch so 
im Speicher liegen!
AUf einem Motorola Rechner liegen sie so im Speicher:  0x5C 0x2E
Auf einem Intel Rechner liegen sie so im Speicher:     0x2E 0x5C

Schickst du einfach die Bytes in der Reihenfolge, wie sie im Speicher 
liegen weg, so erhält sie der Empfänger in einer der beiden 
Reihenfolgen. Setzt er sie falsch zusammen, dann erhält er eine ganz 
andere Zahl.

Bei 4 Bytes gibt es dann noch mehr Möglichkeiten

> Vielleicht habe ich auch gerade einen Denkfehler, oder übersehe etwas,
> da ich in dem Bereich der Programmierung noch recht neu bin.

Schau dir endlich die Einzelbytes an, die dein Programm erhält. Und zwar 
als Hex-Zahlen.

> Könnte es sein, dass meine 0-Bytes den Datenstrom terminieren, da ich ja
> über char-arrays sende?

Wie sieht dein Sendecode aus?

Du musst strikt zwischen einer reinen binären Übertragung und einer 
Übertragung in Textform unterscheiden. Das sind andere Funktionsaufrufe. 
Bei einer reinen binären Übertragung gibt es auch dein 0-Byte welches 
irgendwas terminieren könnte. Jedes Byte wird übertragen so wie es eben 
ist.

Also was machst du jetzt eigentlich:
Übertragung in Textform
oder rein binäre Übertragung?

von Cassidy (Gast)


Lesenswert?

Die Übertragung ist rein binär.

Da ich jetzt die Paketgröße berechnet habe und vorgegeben habe, klappt 
die Übertragung an sich auch. Allerdings stellt sich ein neues Problem.

Die Daten kopiere ich per memcpy() in den Buffer.
Allerdings werden die  Werte "invertiert" gesendet, da ich ein 
Little-Endian System habe.
Gibt es eine Möglichkeit dies zu ändern bzw. eine einheitliche 
Reihenfolge unabhängig vom System zu haben.

Gruß Cassidy

von Udo S. (urschmitt)


Lesenswert?

Wenn Du über Ethernet sendest und ich mich nicht ganz irre, dann gibt es 
dafür ein fixes Byte ordering genannt "Network byte ordering". Soweit 
ich mich erinnere ist das für Ethernet Big Endian.
Little Endian Systeme konvertieren ihre Zahlen dann normalerweise in der 
Netztzugriffs-API.

von Karl H. (kbuchegg)


Lesenswert?

Es gibt normalerweise Funktionen

htons     Host to Network Short
htonl     Host to Network Long
ntohs     Network to Host Short
ntohl     Network to Host Long


gemeint ist jeweils: Die Byteorder auf/zu dem auf dem Hostsystem 
vorliegenden Endianess umdrehen.

Ob du sie auf deinem System hast oder nicht (kommt mit den TCP/IP 
Libararies) musst du abklären. Wenn nicht solltest du dir die 
entsprechenden Funktionen machen und die dann benutzen anstatt deinen 
Code an allen möglichen Stellen mit den entsprechenden händischen 
Konvertierungen zu spicken.

Ach ja: Der Sendcode sollte ebenfalls sein Daten mit den entsprechenden 
Aufrufen in die Standard-Network Byteorder umkonvertieren. Das vermeidet 
zukünftige Probleme.

von Cassidy (Gast)


Lesenswert?

Gibt es für AVR eine vorgefertigte Bibliothek dafür oder irgendwo eine 
Erklärung / Beispiel Implementierung der hton/ntoh Befehle?

Grüße Cassidy

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.