Eğer DNS'in ne olduğunu bilmiyorsanız söyleyeyim: "Domain Name System"
yani "Alan Adı Sistemi" demek. Kısaca siz ona kolayca
hatırlayabildiğiniz adresi verirsiniz o da size buna karşılık gelen
IP adresini verir (ki siz de bu bilgiyi bind(),
connect(), sendto() ve diğer
işlevleri çağırırken kullanabilesiniz). Böylece biri:
komutunu girdiğinde telnet yazılımı
connect() işlevine verilmesi gereken
"198.137.240.92" bilgisine erişebilir.
Peki bu nasıl çalışır? Bunun için gethostbyname()
işlevini kullanacaksınız:
#include <netdb.h>
struct hostent *gethostbyname(const char *name);
Gördüğünüz gibi bu işlev struct hostent türünde
bir gösterge döndürür. Söz konusu türün ayrıntılı yapısı da şöyledir:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
};
#define h_addr h_addr_list[0]
Bu karmaşık değişkenin içindeki alanların açıklamalarına gelince:
h_name -- Konağın resmi ismi.
h_aliases -- Söz konusu konağın alternatif
isimleri, NULL ile sonlandırılmış karakter dizileri şeklinde.
h_addrtype -- Dönen adresin türü, genellikle
AF_INET değerini alır.
h_length -- Byte cinsinden adresin uzunluğu.
h_addr_list -- Konağın ağ adresinin
sıfır sonlandılmalı dizisi. Konak adresleri ağ bayt sıralamasına
sahiptir.
h_addr -- h_addr_list
listesindeki ilk adres.
gethostbyname() çalıştıktan sonra içini doldurduğu
struct hostent türünden bir gösterge döndürür. Eğer
hata oluşursa NULL döndürür. (Fakat errno
değişkeni ile ilgili herhangi bir işlem yapmaz -- bunun yerine
h_errno değişkeni kullanılır. Ayrıntılı bilgi için
aşağıdaki herror() işlevine bakın.)
Peki tüm bu bilgileri nasıl kullanacağız? Bazen okuyucuya bilgi
yığınını verip onu bununla başbaşa bırakmak yeterli olmaz (bilgisayar
belgelerini okuyanlar ne demek istediğimi anlıyorlardır). Bu işlevi
kullanmak düşündüğünüzden daha kolaydır.
/*
** getip.c -- konak isminden IP adresini elde edilmesi
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
struct hostent *h;
if (argc != 2) { // komut satırında hata denetimi
fprintf(stderr,"usage: getip konak_ismi\n");
exit(1);
}
if ((h=gethostbyname(argv[1])) == NULL) { // konak bilgilerini al
herror("gethostbyname");
exit(1);
}
printf("Konak ismi: %s\n", h->h_name);
printf(" IP Adresi: %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));
return 0;
}
gethostbyname() söz konusu olduğunda
perror() işlevini hata mesajını basmak için
kullanamazsınız (çünkü errno gerekli değeri
almaz). Bunun yerine herror() işlevini
kullanmalısınız.
Açıklama basit: Doğrudan ilgilendiğiniz makinanın Internet adresini
verirsiniz ("whitehouse.gov") ve gethostbyname()
işlevi de çalışıp işini bitirdikten sonra size
struct hostent türünde bir değişken döndürür.
Buradaki tek gariplik şudur: IP adresini basarken kullanmanız gereken
h->h_addr, char* türündedir
ama inet_ntoa() işlevi struct in_addr
türünde bir değişken isteme konusunda ısrarcı olduğu için önce
h->h_addr değiğkenini
struct in_addr* türüne çevirdim ve ardından veriye
ulaştım.