GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Zweck der sendto-Adresse für C-Raw-Socket?

Mit send in den Socket schreiben schlägt fehl und sagt mir, dass ich eine Adresse angeben muss.

Es schlägt fehl, weil die send() Funktion kann nur auf verbunden verwendet werden Steckdosen (wie hier angegeben). Normalerweise würden Sie send() verwenden für TCP-Kommunikation (verbindungsorientiert) und sendto() kann verwendet werden, um UDP-Datagramme (verbindungslos) zu senden.

Da Sie eindeutig verbindungslose "Ping"-Pakete oder besser ICMP-Datagramme versenden möchten, müssen Sie den sendto() verwenden Funktion.

Es scheint keines der zusätzlichen Felder in sendto zu geben sind eigentlich weitgehend gewöhnt. Gibt es also einen technischen Grund, warum ich sendto verwenden muss? statt send oder ist es nur ein Versehen in der API?

Kurze Antwort:

Wenn Sie send() nicht verwenden dürfen , dann bleibt nur noch eine Option namens sendto() übrig .

Lange Antwort:

Es ist nicht nur ein Versehen in der API. Wenn Sie ein UDP-Datagramm über einen gewöhnlichen Socket senden möchten (z. B. SOCK_DGRAM ), sendto() benötigt die Informationen über die Zieladresse und den Port, die Sie in der Struktur sockaddr_in angegeben haben , Rechts? Der Kernel fügt diese Informationen in den resultierenden IP-Header ein, da die Struktur sockaddr_in ist die einzige Ort, an dem Sie angegeben haben, wer der Empfänger sein wird. Oder anders gesagt:In diesem Fall muss der Kernel die Zielinformationen aus Ihrer Struktur nehmen, da Sie keinen zusätzlichen IP-Header bereitstellen.

Weil sendto() nicht nur für UDP, sondern auch für Raw-Sockets verwendet wird, muss es eine mehr oder weniger "generische" Funktion sein, die alle verschiedenen Anwendungsfälle abdecken kann, auch wenn einige Parameter wie die Portnummer am Ende nicht relevant/verwendet werden.

Zum Beispiel durch Verwendung von IPPROTO_RAW (was automatisch IP_HDRINCL impliziert ) zeigen Sie Ihre Absicht, den IP-Header selbst erstellen zu wollen. Also die letzten beiden Argumente von sendto() sind eigentlich redundante Informationen, da sie bereits in dem Datenpuffer enthalten sind, den Sie an sendto() übergeben als zweites Argument. Beachten Sie dies, auch wenn Sie IP_HDRINCL verwenden Mit Ihrem Raw-Socket füllt der Kernel die Quelladresse und die Prüfsumme Ihres IP-Datagramms aus, wenn Sie die entsprechenden Felder auf 0 setzen .

Wenn Sie Ihr eigenes Ping-Programm schreiben möchten, können Sie auch das letzte Argument in Ihrem socket() ändern Funktion von IPPROTO_RAW bis IPPROTO_ICMP und lassen Sie den Kernel den IP-Header für Sie erstellen, damit Sie sich um eine Sache weniger Sorgen machen müssen. Jetzt können Sie leicht sehen, wie die beiden sendto() -Parameter *dest_addr und addrlen wieder an Bedeutung gewinnen, weil es der einzige Ort ist, an dem Sie eine Zieladresse angeben.

Die Sprache und die APIs sind sehr alt und mit der Zeit gewachsen. Einige APIs können aus heutiger Sicht seltsam aussehen, aber Sie können die alten Schnittstellen nicht ändern, ohne eine große Menge vorhandenen Codes zu beschädigen. Manchmal muss man sich einfach an Dinge gewöhnen, die vor vielen Jahren oder Jahrzehnten definiert/entworfen wurden.

Ich hoffe, das beantwortet Ihre Frage.


Der send() Aufruf wird verwendet, wenn sich die Sockets in einem TCP SOCK_STREAM befinden verbundener Zustand.

Aus der Manpage:

Der send()-Aufruf darf nur verwendet werden, wenn sich der Socket in einem verbundenen Zustand befindet (so dass der beabsichtigte Empfänger bekannt ist).

Da sich Ihre Anwendung offensichtlich mit keinem anderen Socket verbindet, können wir send() nicht erwarten zu arbeiten.


Linux
  1. Der Zweck des Schlüsselworts „do“ in Bash-For-Schleifen?

  2. Quelladresse für Whois-Abfragen kontrollieren?

  3. Überlegungen zur Migration zu einem Allzweck- oder E/A-Cloud-Server

  4. Python-Raw-Socket:Protokoll wird nicht unterstützt

  5. Raw-Socket in Python ohne Root-Rechte erstellen

ppl – Ein Befehlszeilen-Adressbuch für Linux

Statische und dynamische IP-Adresskonfigurationen für DHCP

Die 10 besten Tools zur Verwaltung von IP-Adressen für Linux

Statische IP-Adresse mit NetworkManager für Fedora

GPSD-Adresse für ntpd abrufen

Wie ändere ich das Von:Feld für E-Mails von Cron?