GNU/Linux >> Znalost Linux >  >> Linux

Účel adresy sendto pro C raw socket?

Zápis do zásuvky pomocí send selže a říká mi, že musím zadat adresu.

Selže, protože send() funkci lze použít pouze na připojeno zásuvky (jak je zde uvedeno). Obvykle byste použili send() pro komunikaci TCP (orientovaná na spojení) a sendto() lze použít k odesílání datagramů UDP (bez připojení).

Protože chcete posílat pakety "ping", nebo přesněji ICMP datagramy, které jsou zjevně nespojitelné, musíte použít sendto() funkce.

Zdá se, že žádné z dalších polí v sendto jsou skutečně ve velké míře využívány. Existuje tedy technický důvod, proč musím používat sendto místo send nebo je to jen přehlédnutí v API?

Krátká odpověď:

Když nemáte povoleno používat send() , pak zbývá pouze jedna možnost, nazvaná sendto() .

Dlouhá odpověď:

Nejde jen o přehlédnutí v API. Pokud chcete odeslat datagram UDP pomocí běžného soketu (např. SOCK_DGRAM ), sendto() potřebuje informace o cílové adrese a portu, které jste uvedli ve struktuře sockaddr_in , že jo? Jádro vloží tyto informace do výsledné IP hlavičky, protože struktura sockaddr_in je jediný místo, kde jste uvedli, kdo bude příjemce. Nebo jinými slovy:v tomto případě musí jádro převzít informace o cíli z vaší struktury, protože nezadáte další IP hlavičku.

Protože sendto() se nepoužívá pouze pro UDP, ale také pro raw sockety, musí to být víceméně "obecná" funkce, která dokáže pokrýt všechny různé případy použití, i když některé parametry jako číslo portu nejsou nakonec relevantní/použité.

Například pomocí IPPROTO_RAW (což automaticky znamená IP_HDRINCL ), ukážete svůj záměr, že chcete vytvořit hlavičku IP sami. Tedy poslední dva argumenty sendto() jsou ve skutečnosti redundantní informace, protože jsou již zahrnuty v datové vyrovnávací paměti, kterou předáváte do sendto() jako druhý argument. Pamatujte, že i když používáte IP_HDRINCL s vaším raw socketem jádro vyplní zdrojovou adresu a kontrolní součet vašeho IP datagramu, pokud nastavíte odpovídající pole na 0 .

Pokud chcete napsat svůj vlastní pingový program, můžete také změnit poslední argument v socket() funkce z IPPROTO_RAW na IPPROTO_ICMP a nechte jádro, aby za vás vytvořilo IP hlavičku, takže máte o jednu starost méně. Nyní můžete snadno vidět, jak jsou dva sendto() -parametry *dest_addr a addrlen se opět stane významným, protože je to jediné místo, kde zadáte cílovou adresu.

Jazyk a API jsou velmi staré a postupem času se rozrostly. Některá rozhraní API mohou z dnešního pohledu vypadat divně, ale nemůžete změnit stará rozhraní, aniž byste narušili obrovské množství existujícího kódu. Někdy si prostě musíte zvyknout na věci, které byly definovány/navrženy před mnoha lety nebo desetiletími.

Doufám, že to odpoví na vaši otázku.


send() volání se používá, když jsou sokety v TCP SOCK_STREAM připojený stav.

Z manuálové stránky:

volání send() lze použít pouze v případě, že je soket v připojeném stavu (takže je znám zamýšlený příjemce).

Protože se vaše aplikace zjevně nepřipojuje k žádnému jinému soketu, nemůžeme očekávat send() do práce.


Linux
  1. python raw socket:Protokol není podporován

  2. Nelze přidat perf sondu pro metody C++

  3. Získání adresy gpsd pro ntpd

  1. Řídit zdrojovou adresu pro dotazy Whois?

  2. Úvahy o migraci na cloudový server pro obecné účely nebo I/O

  3. Jak změnit pole Od:pro e-maily z Cronu?

  1. Získání MAC adresy

  2. jak navázat raw socket na konkrétní rozhraní

  3. Vytváření raw socketu v Pythonu bez práv roota