Şanslısınız çünkü IP adresleri ile uğraşmanızı sağlayacak bir grup
işlev vardır. Yani elle hesap kitap yapıp sonra da bunu bir
long içine <<
işleci ile tıkıştırmanıza gerek yok.
Önce örneğin elinizde bir struct sockaddr_in ina
değişkeni ve bir de 10.12.110.57 şeklinde bir
IP adresi olduğunu var sayalım. Bu adresi bu değişken içine
yerleştirmek istiyorsunuz. Kullanmanız gereken işlev:
inet_addr(). Bu işlev bir IP adresini
yukarıdaki gibi sayılardan ve noktalardan oluşan bir biçemden alıp
unsigned long türünde bir sayıya çevirir. Bu tür
bir atama şu şekilde yapılabilir:
ina.sin_addr.s_addr = inet_addr("10.12.110.57");
Şuna dikkat edin: inet_addr() zaten döndürdüğü
değeri Ağ Bayt Sıralamasına göre dizilmiş olarak döndürür yani
htonl() işlevini burada çağırmanıza gerek yok.
Harika!
Yukarıdaki kod parçası pek sağlam sayılmaz çünkü hiç hata denetimi yok.
Gördüğünüz gibi inet_addr() hatalı bir durumla
karşılaşınca -1 değerini döndürür. İkili sayı
sistemini hatırladınız mı? (unsigned)-1 tam da
şu IP adresine karşılık gelir: 255.255.255.255!
Bu da yayın adresidir! Aman dikkat. Hata kontrolünü düzgün bir şekilde
yapmayı sakın ihmal etmeyin.
Aslında inet_addr() yerine kullanabileceğiniz
daha güzel bir işlev var: inet_aton() ("aton"u,
"ascii to network" olarak okuyun):
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
Bir örnek vermek gerekirse: bu işlev
struct sockaddr_in
yapısını paketlerken (ilerledikçe bu örnek size daha da anlamlı
gelecek
bind()
ve
connect()
kısımlarına kadar sabredin.)
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET; // konak bayt sıralaması
my_addr.sin_port = htons(MYPORT); // short, ağ bayt sıralaması
inet_aton("10.12.110.57", &(my_addr.sin_addr));
memset(&(my_addr.sin_zero), '\0', 8); // geriye kalanı sıfırla
inet_aton(), diğer tüm soket-bağlantılı
işlevlerden farklı olarak, sorun çıkmazsa sıfırdan farklı bir değer,
sorun çıkarsa da sıfır değerini döndürür. Ve döndürülen adres
inp içinde yer alır.
Maalesef her platform inet_aton() işlevini
kullanmamaktadır. Bu yüzden her ne kadar bu işlevi tercih etsek de
daha yaygın olması itibariyle örneklerde
inet_addr() kullanılacaktır.
Artık IP adreslerini ikilik sisteme kolayca dönüştürebileceğinize
göre bunun tersini yapmaya ne dersiniz? Yani mesela elinizde zaten
bir struct in_addr yapısı varsa ve siz bunu alışık
olduğunuz sayılı noktalı IP adresi biçeminde basmak istiyorsanız?
Bu durumda kullanacağımız işlev: inet_ntoa()
("ntoa"yı "network to ascii" olarak okuyun). Şu şekilde işinizi görür:
printf("%s", inet_ntoa(ina.sin_addr));
Bu IP adresini basacaktır. Dikkat edin: inet_ntoa()
argüman olarak struct in_addr alır long
almaz. Bir diğer önemli nokta da: Bu işlev bir char'a
işaret eden bir gösterge döndürür. Söz konusu gösterge
inet_ntoa() içinde statik olarak depolanan bir
karakter dizisine işaret eder ve inet_ntoa()
işlevini her çağırışınızda son işlem görmüş olan IP adresinin üzerine
yazılır. Örneğin:
char *a1, *a2;
.
.
a1 = inet_ntoa(ina1.sin_addr); // burada 192.168.4.14 var
a2 = inet_ntoa(ina2.sin_addr); // burada 10.12.110.57 var
printf("1. adres: %s\n",a1);
printf("2. adres: %s\n",a2);
şunu basar:
1. adres: 10.12.110.57
2. adres: 10.12.110.57
Eğer birden fazla adresle iş yapıyorsanız ve bunları yukarıda olduğu
gibi kaybetmek istemiyorsanız o zaman strcpy()
gibi bir işlev kullanarak uygun bir yere kopyalamayı sakın ihmal
etmeyin.