Hallo miteinander
Ich möchte mittels UDP zwischen einem TMS320F28388D Microcontroller
(192.168.0.4) und einem Linux PC (192.168.0.1) kommunizieren habe aber
das Problem, dass der uC auf welchem der lwip stack läuft, nicht richtig
auf den Empfang des UDP Packets reagiert.
Die Sockets auf beiden Seiten sind mit dem Port 3030 verbunden.
Wenn der Linux PC das erste Packet sendet, antwortet der lwip stack mit
einer ICMP Nachricht "Destination unreachable (Port unreachable)",
obwohl ich eigtl. einen Socket auf dem Mikrocontroller erzeuge, der mit
diesem Port verbunden sein sollte.
Hat vielleicht jemand eine Idee, wo mein Problem liegen könnte?
Nachfolgend mein Code:
Aufsetzen des UDP sockets:
1
const u16_t COMM_PORT=3030;
2
struct udp_pcb* current_udp_pcb;
3
ip_addr_t IPAddr_remote={0xC0A80001}; //ip address of the remote pc
4
5
void setupCommInterface(void){
6
//create a new udp pcb
7
current_udp_pcb = udp_new();
8
//bind the pcb to the port comm_port
9
//this receives on port COMM_PORT from any IP address
Bei TCP/IP-APIs müssen IP-Adressen und Ports oft in "network byte order"
angegeben werden. Ob im lwip auch weiss ich nicht. Dazu gibts
üblicherweise sowas wie htons().
Tom schrieb:> Ich möchte mittels UDP kommunizieren> Die Sockets auf beiden Seiten sind mit dem Port 3030 verbunden.
Das kann nicht sein. Sockets (Verbindungen) gibt es nur bei TCP.
UDP ist wie Postkarten bei der Deutschen Post. Du schickst ein UDP Paket
irgendwohin und hoffentlich kommt es an. Vielleicht auch nicht. Du wirst
es nie erfahren.
Das heißt, die Meldung "Destination unreachable (Port unreachable)"
halte ich für unmöglich.
Zum Testen empfehle ich dir das Programm "netcat". Damit kannst du
sowohl TCP als auch UDP in beide Richtungen testen. Beispiel:
In einem Fenster starte ich einen UDP Listener:
1
sfrings@stefanspc:~$ nc -l -u -p 3000
In einem anderen Fenster sende ich ein UDP Paket:
1
sfrings@stefanspc:~$ nc -u localhost 3000
2
Hallo
Ergebnis im ersten Fenster:
1
sfrings@stefanspc:~$ nc -l -u -p 3000
2
Hallo
Gegentest: Sende etwas an einen "falschen" Port:
1
sfrings@stefanspc:~$ nc -u localhost 3001
2
Möööp
Du bekommst keine Fehlermeldung. Das Paket landet im Nirvana. Das ist
bei UDP so beabsichtigt.
Ich möchte nochmal auf meinen obigen Satz zurück kommen:
> Das kann nicht sein. Sockets (Verbindungen) gibt es nur bei TCP.
Bei der uIP Biblipthek (vom selben Author) wird der Begriff "connection"
im Kontext von UDP missbraucht. Man tut so, als würde man eine
Verbindung zu einem partner aufbauen. Tatsächlich hat man aber nur
festgelegt, auf welchem Port man künftig etwas empfangen will, bzw.
wohin man etwas Senden will. Das "öffnen" einer UDP Verbindung findet
nur im RAM des Mikrocontrollers statt, dabei findet noch keine
Kommunikation auf dem Kabel statt.
Mir ist klar, dass damit dein Problem nicht gelöst ist. Aber ich hoffe,
dass diese Info dir hilft, das UDP Protokoll zu verstehen damit du das
Problem gezielter weiter untersuchen kannst.
Stefan ⛄ F. schrieb:> Das kann nicht sein. Sockets (Verbindungen) gibt es nur bei TCP.
Das stimmt natürlich nicht. Sockets sind zwar irgendwie schon
"Verbindungen", aber nicht im Sinne einer TCP-Verbindung, wie du
scheinbar glaubst.
Sockets sind eine Abstraktion und können dann Ausprägungen in
verschiedene konkrete Typen haben. Such' einfach mal mit Google nach
"SocketType" und staune, wieviele (durchaus verschiedene) Enumerationen
du findest. Das zeigt ganz klar, dass dieses allgemeine Socket-Konzept
in vielen Sprachen und Frameworks verwendet wird.
Bei lwip (um was es im Thread ging), heißt das ein wenig anders als
üblich, aber es ist das gleiche Konzept wie üblich. Siehe sockets.c ab
Zeile 158.
Stefan ⛄ F. schrieb:> Tom schrieb:>> Ich möchte mittels UDP kommunizieren>> Die Sockets auf beiden Seiten sind mit dem Port 3030 verbunden.>> Das kann nicht sein. Sockets (Verbindungen) gibt es nur bei TCP.>> UDP ist wie Postkarten bei der Deutschen Post. Du schickst ein UDP Paket> irgendwohin und hoffentlich kommt es an. Vielleicht auch nicht. Du wirst> es nie erfahren.>> Das heißt, die Meldung "Destination unreachable (Port unreachable)"> halte ich für unmöglich.
Och Stefan...
Auch bei UDP unterscheidet der IP-Stack, ob auf dem jeweiligen Port
etwas lauscht (was per bind() passiert), und wenn nicht, geht die o.g.
ICMP-Message zurück.
$ echo "test" | nc -u 127.0.0.1 12345
16:48:13.581316 IP 127.0.0.1.55734 > 127.0.0.1.12345: UDP, length 5
16:48:13.581398 IP 127.0.0.1 > 127.0.0.1: ICMP 127.0.0.1 udp port 12345
unreachable, length 41
Stefan ⛄ F. schrieb:> Bei der uIP Biblipthek (vom selben Author) wird der Begriff "connection"> im Kontext von UDP missbraucht. Man tut so, als würde man eine> Verbindung zu einem partner aufbauen. Tatsächlich hat man aber nur> festgelegt, auf welchem Port man künftig etwas empfangen will, bzw.> wohin man etwas Senden will.
Da wird nichts missbraucht, so ist es im POSIX-Umfeld bei connect()
auch:
https://pubs.opengroup.org/onlinepubs/009695399/functions/connect.html
Dort wird natürlich keine Verbindung im Sinne eines Handshakes
hergestellt, sondern dafür gesorgt, dass zum einen per send() statt
sendto() verschickte Pakete dort hingehen und zum anderen nur noch
Pakete angenommen werden, die von dieser Gegenstelle kommen.
Ok, streichen wir die Sockets aus meiner Antwort.
Ich bleibe dabei, dass UDP keine Verbindungen kennt. Ob ein gesendetes
Paket den Empfänger erreicht hat und ob der Empfänger empfangsbereit
war, erfährt der Sender nicht. Es gibt da keinerlei Rückmeldung.
Die müsste man ggf. selbst auf Anwendungs-Ebene implementieren.
Destination unreachable hört sich doch sehr nach IP an, also Layer 3.
Kannst du das Ding überhaupt anpingen? Probier das erstmal, bevor du UDP
ins Layer 4 schickst.
TTL schrieb:> Destination unreachable hört sich doch sehr nach IP an, also Layer 3.> Kannst du das Ding überhaupt anpingen?
Type "Destination unreachable", Code "Port unreachable" und kommt von
der Zieladresse.
Auf Layer 3 ist alles in Ordnung, der IP-Stack ist bloss der Meinung,
dass auf diesem UDP-Port nichts lauscht.
Es wäre mal interessant zu wissen, was udp_bind() zurückliefert. Die
momentane Fehlerbehandlung sieht ja noch eher rudimentär aus.
Moin,
Stefan ⛄ F. schrieb:> Ich bleibe dabei, dass UDP keine Verbindungen kennt. Ob ein gesendetes> Paket den Empfänger erreicht hat und ob der Empfänger empfangsbereit> war, erfährt der Sender nicht.
Der Sender muss es nicht erfahren. Wenn aber der Netzwerkstack des
Empfaengers "nett" ist, dann kann er sehr wohl dem Sender Bescheid
sagen; es ist nicht verboten, dann ein entsprechendes ICMP wie im
Wireshark im 1. Post sichtbar zurueckzuschicken...
Gruss
WK
Stefan ⛄ F. schrieb:> Ok, streichen wir die Sockets aus meiner Antwort.
Besser ist das...
> Ich bleibe dabei, dass UDP keine Verbindungen kennt. Ob ein gesendetes> Paket den Empfänger erreicht hat und ob der Empfänger empfangsbereit> war, erfährt der Sender nicht. Es gibt da keinerlei Rückmeldung.
Natürlich ist das so. Deswegen halt "Datagram" und nicht "Stream". Das
unterscheidet die beiden Socket-Typen. Aber es gibt trotzdem viele
Gemeinsamkeiten. Auch bei der Benutzung. Genau deswegen war es ja
sinnvoll, die Socket-Sache als eine gemeinsame Abstraktion einzuführen.
> Die müsste man ggf. selbst auf Anwendungs-Ebene implementieren.
Oder besser gleich TCP verwenden? Das existiert, ist gut durchgetestet
und funktioniert.
c-hater schrieb:> Oder besser gleich TCP verwenden? Das existiert, ist gut durchgetestet> und funktioniert.
Je nach Anwendung kann TCP auch nachteilig sein.
(prx) A. K. schrieb:> Je nach Anwendung kann TCP auch nachteilig sein.
Natürlich. Wäre es nicht so, gäbe es UDP nicht. Aber wenn man die
Eigenschaften von TCP will/braucht, dann ist es definitiv Schwachsinn,
auf höherer Ebene was eigenes, auf UDP basierendes zu bauen, um das zu
erreichen. Da nimmt man natürlich TCP.