Překlad doménových jmen v Linuxu - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Překlad doménových jmen v Linuxu

cpp net

25. listopadu 2002, 00.00 | Dnes si ukážeme jak V OS Linux a jiných Unixových OS překládat doménová jména na IP adresy. Na konci článku je malý ukázkový příklad ke stažení.

V minulém článku jsem si řekli, že IP adresa je číslo. Problém je v tom, že pamatovat si čísla je velice nepraktické. Například kdo by si pamatoval http://212.80.76.3. Proto byly zavedeny tak zvané doménové jména. Jedná se o textové řetězce, které se lépe pamatují. Například http://www.seznam.cz zná u nás snad každý. Málo kdo ale ví, že předchozí dvě adresy jsou stejné. Důvod, proč se zavedly doménové jména je čistě praktický.
Budeme-li chtít komunikovat pomocí soketů, budeme potřebovat znát IP adresy vzdálených počítačů. Nejčastěji ale budeme znát (od uživatelů) doménová jména. Dnes si ukážeme jak doménová jména překládat na IP adresy.

Struktury

Nejprve se podívejme na důležité struktury hostent a in_addr.

Struktura hostent

Struktura je definována v hlavičkovém souboru netdb.h. Instance struktury charakterizuje vzdálený počítač. Struktura obsahuje atributy:

  • char *h_name - řetězec s oficiálním názvem vzdáleného počítače.
  • char **h_aliases - pole ukazatelů na "C řetězce" zakončené NULL. V řetězcích jsou uloženy alternativní názvy počítače. Pomocí alternativních názvů lze také přistupovat ke vzdálenému počítači.
  • int h_addr_type - číslo udávající typ adresy. Vždy bude odpovídat hodnotě makra AF_INETP. My si ji v podstatě nebudeme všímat.
  • int h_length - velikost adresy v bytech. Jak jsem uváděl minule, IP adresa ve verzi IP4 má 4 byte. V novějších verzích tomu tak ale již není. Protože IP4 je nejpoužívanější, bude tato položka struktury pravděpodobně vždy nabývat hodnoty 4.
  • char **h_addr_list - nejprve musím upozornit, že se NEJEDNÁ o pole ukazatelů na "C řetězce". Jedná se o pole ukazatelů zakončené ukazatelem NULL. Každý ukazatel ukazuje na pole bytů (char) velikosti rovné hodnotě atributu h_length (tedy většinou 4 byte). V každém z těchto h_length-bytových polích se nachází IP adresa vzdáleného počítače.

Ještě také existuje prvek char *h_addr, který obsahuje první prvek z pole h_addr_list. Tento prvek je zde z důvodu zpětné kompatibility a já Vám nedoporučuji jej používat. Vždy můžete použít h_addr_list[0]. Když jsem mluvil o h_addr úmyslně jsem se vyhýbal slovu atribut. Není to totiž atribut struktury hostent. Je to makro definované takto:
#define h_addr h_addr_list[0]
a je zde opravdu jen z důvodů zpětné kompatibility.

Struktura in_addr

Struktura je definována v hlavičkovém souboru netinet/in.h. O této struktuře není důležité vědět, jaké má atributy. Navíc myslím, že budou systém od systému jiné. Instance struktury in_addr se budou používat jako parametry některých funkcí. Máme-li IP adresu ve tvaru, v jakém je jeden prvek pole h_addr_list, můžeme jej přetypovat na strukturu in_addr a použít jako parametr nějaké funkce.

Funkce pro práci s adresami a doménovými jmény

Pro překlad doménového jména na IP adresu (resp. pro získání struktury hostent z doménového jména) slouží funkce gethostbyname. Chceme-li získat strukturu hostent z IP adresy, slouží nám k tomu funkce gethostbyaddr. Chceme-li získat IP adresu v pro člověka čitelném tvaru, použijeme funkci inet_ntoa.

  • struct hostent *gethostbyname(const char *name); - parametrem funkce je doménové jméno. Například "www.seznam.cz". Funkce vrací ukazatel na strukturu hostnet v případě, že nedošlo k chybě. Jestliže došlo k chybě funkce vrací NULL. V případě chyby bude také číselný kód chyby zapsán do globální proměnné h_errno. Funkce je deklarována v hlavičkovém souboru netdb.h. Je-li parametrem IP adresa v "tečkovém" tvaru (například 212.80.76.3), funkce vrátí instanci struktury hostent, ve které je zkopírován v atributu h_name parametr funkce a atribut h_addr_list[0] je zaplněn binární obdobou IP adresy. Je tedy možné dát jako parametr funkce IP adresu v tečkové konvenci. V tomto případě ale nedojde k žádnému překladu pomocí DNS serveru. Bude vytvořena instance struktury a do ní budou zkopírovány dva údaje. Jestliže zadaná adresa neexistuje, nedojde k chybě. Máte-li IP adresu a chcete k ní získat strukturu hostent, je vhodnější použít funkci gethostbyaddr.
  • struct hostent *gethostbyaddr(const char *addr, int len, int type); - parametr addr je ukazatel na IP adresu ve tvaru posloupnosti bytů. Pro IP protokol verze 4 se bude jednat o posloupnost 4 bytů. Parametr len udává velikost adresy. Parametr type má vždy hodnotu makra AF_INET. Funkce vrací strukturu hostent pro danou adresu. V případě chyby vrací NULL a kód chyby vloží do globální proměnné h_errno. Funkce je deklarována v hlavičkovém souboru netdb.h.
  • char *inet_ntoa(struct in_addr in); - funkce slouží pro převod IP adresy ve formě posloupnosti bytů na řetězec ve "tečkovém" tvaru. Parametrem je IP adresa v binárním tvaru přetypovaná na typ in_addr. Funkce je deklarována v hlavičkovém souboru arpa/inet.h.
Příklad

Jako ukázkový příklad těchto funkcí si ukážeme program pro překlad doménových jmen. Program bude jednoduchá konzolová aplikace, která jako svůj parametr získá doménové jméno a vrátí informace o zadaném počítači.

#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
	if (argc != 2)
	{
		std::cerr << "Syntaxe:\n\t" << argv[0] << " " << "adresa" 
		 << std::endl;
		return -1;
	}
	hostent *H = gethostbyname(argv[1]);
	if (H == NULL)
	{
		std::cerr << "Nepodařilo se zjistit adresu" << std::endl;
	        return -1;
	}
	std::cout << "Oficiální jméno: " << H->h_name << std::endl;
	std::cout << "Alternativy: " << std::endl;
	/* Budeme procházet pole H->h_aliases. Pole je ukončené NULL.*/
        char **alternativy = H->h_aliases;
	while(*alternativy != NULL)
	{
		cout << "\t" << *(alternativy++) << std::endl;
	}
	/* Budeme procházet pole H->h_addr_list. Pole je ukončené NULL. 
           Zvolíme jiný postup než v předchozím případě.*/
	std::cout << "Adresy: " << std::endl;
	register int index = 0;
	while (	H->h_addr_list[index]!= NULL)
	{
	    /* H->h_addr_list je binární forma IP adresy. Pro převod na
	       tečkovou konvenci použijeme inet_ntoa.*/
	    std::cout<<"\t"<< inet_ntoa(*(in_addr *)H->h_addr_list[index++])
	     << std::endl;
	}
	std::cout << "Počet adres: " << index << std::endl;
	std::cout << "Velikost adres: " << H->h_length << std::endl;
	return 0;
}

Jak kompilovat?

K programu nemusíme linkovat žádnou speciální knihovnu. Ukázkový příklad je ke stažení zde. Chcete-li si zkusit adresu s alternativními názvy, můžete zkusit dát jako parametr našemu programu například adresu www.root.cz. Chcete-li vidět počítač s více adresami, můžete zkusit dát třeba www.post.cz

Příště

Příště uděláme stejný program pod MS Windows®. Uvidíte, že zdrojový text bude nápadně podobný. V žádném případě ale nebude stejný. Potom se začneme věnovat programování TCP klienta v OS Linux a OS MS Windows®.


Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: