GNU/Linux >> Tutoriels Linux >  >> Linux

Objectif de l'adresse sendto pour le socket C raw ?

Ecrire sur le socket avec send échoue, me disant que je dois spécifier une adresse.

Cela échoue, car le send() la fonction ne peut être utilisée que sur connecté prises (comme indiqué ici). Habituellement, vous utiliseriez send() pour la communication TCP (orientée connexion) et sendto() peut être utilisé pour envoyer des datagrammes UDP (sans connexion).

Puisque vous voulez envoyer des paquets "ping", ou plus exactement des datagrammes ICMP, qui sont clairement sans connexion, vous devez utiliser le sendto() fonction.

Il semble qu'aucun des champs supplémentaires dans sendto sont en fait largement utilisés. Donc, y a-t-il une raison technique pour laquelle je dois utiliser sendto au lieu de send ou est-ce juste un oubli dans l'API ?

Réponse courte :

Lorsque vous n'êtes pas autorisé à utiliser send() , alors il ne reste qu'une seule option, appelée sendto() .

Réponse longue :

Ce n'est pas seulement un oubli dans l'API. Si vous souhaitez envoyer un datagramme UDP en utilisant un socket ordinaire (par exemple SOCK_DGRAM ), sendto() a besoin des informations sur l'adresse et le port de destination, que vous avez fournies dans la structure sockaddr_in , droit? Le noyau insérera ces informations dans l'en-tête IP résultant, puisque la structure sockaddr_in est le seul endroit où vous avez spécifié qui sera le destinataire. Ou en d'autres termes :dans ce cas, le noyau doit prendre les informations de destination de votre structure car vous ne fournissez pas d'en-tête IP supplémentaire.

Parce que sendto() n'est pas seulement utilisé pour UDP mais aussi pour les sockets bruts, il doit s'agir d'une fonction plus ou moins "générique" qui peut couvrir tous les différents cas d'utilisation, même lorsque certains paramètres comme le numéro de port ne sont finalement pas pertinents/utilisés.

Par exemple, en utilisant IPPROTO_RAW (ce qui implique automatiquement IP_HDRINCL ), vous montrez votre intention de créer vous-même l'en-tête IP. Ainsi les deux derniers arguments de sendto() sont en fait des informations redondantes, car elles sont déjà incluses dans le tampon de données que vous transmettez à sendto() comme deuxième argument. Notez que, même lorsque vous utilisez IP_HDRINCL avec votre socket brut, le noyau remplira l'adresse source et la somme de contrôle de votre datagramme IP si vous définissez les champs correspondants à 0 .

Si vous souhaitez écrire votre propre programme ping, vous pouvez également modifier le dernier argument de votre socket() fonction de IPPROTO_RAW à IPPROTO_ICMP et laissez le noyau créer l'en-tête IP pour vous, vous avez donc une chose de moins à vous soucier. Maintenant, vous pouvez facilement voir comment les deux sendto() -paramètres *dest_addr et addrlen redeviennent significatifs car c'est le seul endroit où vous fournissez une adresse de destination.

Le langage et les API sont très anciens et ont évolué au fil du temps. Certaines API peuvent sembler étranges du point de vue d'aujourd'hui, mais vous ne pouvez pas modifier les anciennes interfaces sans casser une énorme quantité de code existant. Parfois, il suffit de s'habituer à des choses qui ont été définies/conçues il y a plusieurs années ou décennies.

J'espère que cela répond à votre question.


Le send() call est utilisé lorsque les sockets sont dans un TCP SOCK_STREAM état connecté.

À partir de la page de manuel :

l'appel send() ne peut être utilisé que lorsque le socket est dans un état connecté (afin que le destinataire prévu soit connu).

Étant donné que votre application ne se connecte évidemment à aucune autre socket, nous ne pouvons pas nous attendre à send() travailler.


Linux
  1. Le but du mot-clé "do" dans Bash For Loops ?

  2. Adresse source de contrôle pour les requêtes Whois ?

  3. Obtenir l'adresse MAC

  4. socket raw python :protocole non pris en charge

  5. Création d'un socket brut en Python sans privilèges root

Configurations d'adresses IP statiques et dynamiques pour DHCP

Les 10 meilleurs outils de gestion d'adresses IP pour Linux

Adresse IP statique avec NetworkManager pour Fedora

Obtenir l'adresse gpsd pour ntpd

Comment changer le champ De :pour les e-mails de Cron ?

Spécification de l'adresse IP pour les connexions sortantes sur un hôte multi-IP