Hi, von einem Raspberry Pi will ich per UDP Daten an einen anderen
Rechner senden (Windows-PC). Meine Frage dazu - muss der Rechner, der
die Pakete empfängt, ständig pollen, ob Daten über den UDP-Port
ankommen, damit keine verloren gehen?
Heiko Schmidt schrieb:> Meine Frage dazu - muss der Rechner, der> die Pakete empfängt, ständig pollen, ob Daten über den UDP-Port> ankommen, damit keine verloren gehen?
Nein. Das empfangende Programm wird vom Betriebssystem über einkommende
Daten unterrichtet und schläft ggf bis dahin.
A. K. schrieb:> Das empfangende Programm wird vom Betriebssystem über einkommende> Daten unterrichtet und schläft ggf bis dahin
Wie mache ich das denn dann genau? Muss ich dann mein C-Programm, was
die Daten empfangen soll, an eine Speicherstelle setzen bzw. irgendwie
dem Betriebssystem dann melden, an welcher Speicherstelle sich das
Programm befindet und mir dann z.B. die Daten in ein Array schreibt, die
ich kriege und dann in einem anderen C-Programm weiterverarbeiten kann?
Heiko Schmidt schrieb:> Wie mache ich das denn dann genau?
Im allereinfachsten Fall ist das ähnlich wie bei Files. Du forderst das
Betriebssystem auf, dir Daten zu liefern, und der Aufruf kehrt erst
zurück, wenn es welche gibt.
Tiefergreifende Erkenntnisse über Networking in Anwendungsprogrammen
liefern dir Einführungen in Socket-Programmierung.
Die Vorgänge im Betriebssystem wiederum sprengen den Rahmen einfacher
Forenfragen.
A. K. schrieb:> Im allereinfachsten Fall ist das ähnlich wie bei Files. Du forderst das> Betriebssystem auf, dir Daten zu liefern, und der Aufruf kehrt erst> zurück, wenn es welche gibt.
sowas hab ich mir vorgestellt. Und ggf. kann ich ein Timeout noch
definieren, was dann ggf. den Prozess abbricht.
Heiko Schmidt schrieb:> sowas hab ich mir vorgestellt. Und ggf. kann ich ein Timeout noch> definieren, was dann ggf. den Prozess abbricht.
Nicht den Prozess, sondern den wartenden Betriebssystemaufruf.
Heiko Schmidt schrieb:> Wie mache ich das denn dann genau?
Wenn Du mit der PC-Programmierung nicht vertraut bist und auch nicht
tief einsteigen willst:
https://www.autoitscript.com/site/autoit/downloads/
Die wesentlichen Befehle sind:
UDPBind, UDPRecv, UDPCloseSocket, UDPShutdown()
Hier liefert mein Internetrouter Statusinformationen etc. per UDP auf
die Broadcastadresse des Netzwerks (192.168.xxx.255), die ich per AutoIT
annehme. Ich schaue auf bestimmte Schlüsselworte der Daten und zeige
ggfs. etwas an, zusätzlich schreibe ich alles in ein Logfile.
Ob das nun pollt oder sonstwas macht, weiß ich nicht, das nimmt mir die
Hochsprachenumgebung ab. Was ich sehe, dass es lt. Taskmanager keine
erkennbare Systemlast erzeugt, das genügt mir.
Muss man bei UDP auch etwas wie Server-Client beachten? Muss ich z.B.
meinen Windows-Rechner als Server betrachten, also dort einen Dienst
drauf laufen lassen, der auf den Port horcht bzw. dann Daten sendet und
am anderen Ende dann die Daten empfängt?
Gibt es vlt. auch Netzwerkkarten, die Daten in eiem Puffer
zwischenspeichern können und ein Bit haben, das man abfragen kann, ob
dort was steht? Wenn ich das nicht habe, müsste ich mir ja ein kleines
Programm schreiben, was als horcht und dann die Daten irgendwie puffert
(eben wohl dieser Socket), und dann von diesem Puffer die Daten dann
rausholen.
Heiko Schmidt schrieb:> Muss man bei UDP auch etwas wie Server-Client beachten?
Ob Peer-to-Peer oder Client-Server, das ist Sache der Anwendung. Anders
als bei TCP wird auf Socket-Ebene keine Verbindung aufgebaut. Weshalb
die Rollen von Client und Server auch nicht Teil des Betriebssystems
sind.
> Muss ich z.B.> meinen Windows-Rechner als Server betrachten, also dort einen Dienst> drauf laufen lassen, der auf den Port horcht bzw. dann Daten sendet und> am anderen Ende dann die Daten empfängt?
Wenn ein Prozess auf nichts lauscht, kriegt er auch nichts.
> Gibt es vlt. auch Netzwerkkarten, die Daten in eiem Puffer> zwischenspeichern können und ein Bit haben, das man abfragen kann, ob> dort was steht?
Sind wir noch beim RasPi, oder mittlerweile beim AVR? Solche Feinheiten
darfst du getrost dem Betriebssystem überlassen. An der Netzwerkkarte
hast du nichts verloren.
Aber ja, Netzwerkkarten haben Puffer, Betriebssysteme auch. Und aufs
Netzwerk horchen und puffern tut das Betriebssystem, nicht dein
Programm.
Irgend W. schrieb:> Das ganze entsprechend in eine eigenen thread gepackt
Dafür muss man allerdings die Eigenschaften und Besonderheiten von
Threads kennen und ganz genau darauf achten alles threadsafe zu
programmieren.
Ich kenne natürlich den Wissenstand des TO nicht genau, aber ich
schließe aus den Fragen zu den Konzepten der Netzwerkprogrammierung daß
sein Wissen im Bereich Systemprogrammierung nicht sehr ins Detail
reicht.
Von daher bin ich mir nicht sicher ob ich da gleich Threads empfehlen
würde. Vielleicht lieber erst mal mit Timeout warten.
Gerd E. schrieb:> Von daher bin ich mir nicht sicher ob ich da gleich Threads empfehlen> würde. Vielleicht lieber erst mal mit Timeout warten.
Ich würde einfach mit einem Fifo arbeiten, der ein Semaphorenbit
besitzt, so dass nur ein Prozess Daten reinschreiben oder rausholen kann
- falls Du sowas meinst mit Ablaufproblemen - und der andere Prozess in
dem anderen Thread dann warten muss, bis er dran ist?
Gerd E. schrieb:> daß> sein Wissen im Bereich Systemprogrammierung nicht sehr ins Detail> reicht.
genau, ich bin da noch ganz am Anfang.
A. K. schrieb:> Aber ja, Netzwerkkarten haben Puffer
ich dachte, dass es vielleicht dort so ähnlich sein könnte wie bei
Mikrocontrollern. Wenn dort etwas im Register z.B. für die serielle
Schnittstelle steht, dann wird ein Interrupt ausgelöst. Ich dachte, dass
es sowas vielleicht auch für Netzwerkkarten gegeben hätte.
Aber erstmal vielen Dank für die vielen Hinweise und Tipps, sie haben
zum besseren Verständnis für mich beigetragen und die Hinweise mit dem
Bind, den Sockets ... war ein guter Hinweis. Ich habe in
Python-Beispielen z.B. gesehen, dass dort eine socket-Bibliothek
eingebunden wurde, aber ich wusste zunächst nicht, was es damit auf sich
hatte am Anfang.
> Die Vorgänge im Betriebssystem wiederum sprengen den Rahmen einfacher> Forenfragen.
Ihr werdet es nicht glauben, aber es gibt auch fuer Linux spezielle
Buecher ausschliesslich ueber Netzwerkprogrammierung.
https://www.amazon.de/Netzwerkprogrammierung-unter-Linux-Stefan-Fischer/dp/3446210938
Also mir hat das weitergeholfen. Und 4.50Euro ist deutlich weniger als
man fuer einen Milchshake in so einem modernen Verdummungscafe bezahlt.
.-)
Olaf
Nezwerk-Kommunikation erfolgt über sog. "Sockets", also virtuelle
Software-Schnittstellen, die die verwendete Programmiersprache vom OS
anfordert.
Beim Nachrichtenaustausch wird auf Senderseite in das Socket
"hineingeschrieben" und dann könnte es (z.B. als lokales Objekt in einer
Methode) duchaus "sterben". Für die nächste Sendung wird halt ein neues
Socket erzeugt. Abhängig vom Konzept des Programmierers kann man aber
auch auf Senderseite so ein Socket durchaus auch mehrfach benuzen (als
globales Objekt am Leben erhalten).
Nebenbei müssen die Sockets an beiden Enden der Nachrichtenverbindung
noch kompatibel konfiguriert sein (passende IP, Portnummer, passende
Message-Größe usw.)
Auf der Empfängerseite muss das Socket dagegen die ganze Zeit über
existieren und "am Leben" sein, um keine Sendung zu verpassen.
Einkommende Messages landen zunächst in eimem Puffer und können von dort
gelesen werden.
Wie nun das benutzende Programm davon erfährt, ob denn nun inzwischen
Daten angekommen sind - das geht je nach Programmiersprache auf
unterschideliche Weise, die Wahl trifft wiederum der Programmierer.
Tatsächlich besteht die Möglichkeit, die Größe des Message-Puffers zu
pollen, die sich ja im Falle einer eintreffenden Message von Null auf
irgendwas ändert.
Eine andere Möglichkeit ist es, das Socket mit einem sog.
"Event-Listener" zu verbinden, der beim Eintreffen von Daten "feuert"
und eine Routine aufruft, die die Daten dort ausliest und irgendwas
damit macht ...
Vielleicht fängst Du erstmal mit ner abstrakteren Hochsprache an Dich an
die Socketprogrammierung und die erforderliche Strukturierung des
Programms und der notwendigen Abläufe (Threads oder nicht, Polling oder
blockierend) vorsichtig heranzutasten.
Ich würde zum Beispiel Python vorschlagen, dessen Socket API lässt noch
deutlich das darunterliegende C API durchschimmern (bind, listen,
connect, accept, select, send, recv, etc...) so daß Du alles was Du da
lernst später fast 1:1 auf C übertragen kannst aber da es eine sehr
dynamische Scriptsprache ist lässt sich die Struktur Deines Programms
viel leichtfüßiger mal eben schnell umkrempeln ohne zusätzlich noch die
schwere Ankerkette der ganzen Low-Level-Befindlichkeiten und
Erschwernisse einer Sprache wie C ans Bein gebunden zu haben.
In Python kannst Du Socket-Programmierung (und auch vieles andere auch)
auf fast spielerisch einfache Weise erkunden und lernen und absolut
ALLES was Du da lernst kannst Du später bei C (und auch bei anderen
Sprachen) sehr nutzbringend einsetzen.
Viele Sachen die nicht CPU-lastig sondern eher IO-lastig sind kannst Du
auch direkt in Python lassen, vor allem auf einem PC oder einem
Raspberry wo man nicht die Kilobytes und die Taktzyklen zweimal umdrehen
muss damit sie ausreichen. Für einen Programmieranfänger ist das IMHO
allemal der bessere Einstieg, Du willst nicht an zu vielen Fronten
gleichzeitig kämpfen.
Zu den Low-Level Abgründen systemnaher oder hardwarenaher Sprachen wie C
bei denen man schon das blanke Silizium drunter durchschimmern sehen
kann und den damit verbundenen peniblen Fleißarbeiten und
Sicherheitsmaßnahmen kannst Du später immer noch promovieren sobald Du
glaubst daß Du soweit bist das Wesentliche zu überblicken.
Und selbst dann in dieser zweiten und fortgeschrittenen Phase Deiner
Programmierer-Karriere wirst Du immer noch jederzeit eine dynamische
Hochsprache als nützlichen Helfer und auch als liebgewonnenen Freund
stets hilfsbereit an Deiner Seite haben wollen mit der man jederzeit mal
eben zum Ausprobieren oder Erkunden aus dem Handgelenk heraus monströse
Datenstrukturen und Algorithmen so leicht herum wuchten kann als hätte
jemand die Erdanziehung abgeschaltet.