آدرس های IP و نحوه کار با آنها
خوشبختانه توابع بسیاری برای کار با IP ها وجود دارند. فرض کنید که یک داده از نوع struct sockaddr_in ina دارید و یک آدرس IP دارید "10.12.110.57" و می خواهید آدرس را در آن قرار دهید. تابع inet_addr() یک آدرس IP را به فرم رقم و نقطه می گیرد و آن را به نوع داده ای unsigned long تبدیل می کند. این انتساب را می توان بدین صورت انجام داد:
ina.sin_addr.s_addr = inet_addr("10.12.110.57")
این تابع آدرس را به ترتیب Network Byte Order باز می گرداند و نیازی نیست که تابع htonl() را فراخوانی کنیم.
البته این نحوه کدنویسی اصلا جالب نیست, زیرا هیچ گونه بررسی خطا در آن انجام نشده است. تابع inet_addr() در صورت بروز خطا مقدار -1 را بر می گرداند. مقدار (unsigned) -1 با آدرس 255.255.255.255 برابری می کند. بنابراین توجه داشته باشید که همیشه بررسی خطا را هم انجام دهید.
البته می توانید از تابع inet_aton() که نسبت به inet_addr() از رابط بهتری برخوردار است استفاده نمایید. (aton معادل "ascii to network" است)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
و مثالی عملی از آن:
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET; //host byte order
my_addr.sin_port = htons(MYPORT); //short, network byte order
inet_aton("10.12.110.57", &(my_addr.sin_addr));
memset( &(my_addr.sin_zero), '\0', 8); //zero the rest of the struct
inet_aton(), برخلاف تقریبا همه ی توابع شبکه ای دیگر, در صورت موفقیت عددی غیر صفر باز می گرداند, و در صورت بروز خطا صفر بر می گرداند. آدرس در inp قرار داده خواهد شد.
متاسفانه در همه ی سیستم عامل ها و رایانه ها نمی توان از این تابع استفاده کرد, بنابراین هرچند استفاده از آن ارجحیت دارد, اما ما از تابع قدیمی تر و متداول تر inet_addr() استفاده خواهیم کرد.
بسیار خب. حالا می توانیم آدرس های IP در فرم رشته ای را به معادل دودویی آنها تبدیل کنیم. ولی بر عکس آن چطور؟ در این صورت برای تبدیل یک داده struct in_addr به فرم اعداد و نقطه می توانیم از تابع inet_ntoa() (که ntoa معادل "network to ascii" است) استفاده کنیم. به عنوان مثال:
printf("%s", inet_ntoa(ina.sin_addr));
این کد آدرس IP را چاپ خواهد کرد. توجه داشته باشید که این تابع داده ای از نوع struct in_addr را به عنوان ورودی می گیرد, نه نوع long. همچنین توجه داشته باشید که اشاره گری به نوع char باز گردانده می شود. این اشاره گر به یک آرایه static char درون inet_ntoa() اشاره می کند و بنابراین در هر بار فراخوانی, مقدار آرایه تغییر خواهد کرد و همیشه مقدار آخرین آدرس را نگهداری می کند. به عنوان مثال:
char *a1, *a2;
.
.
a1 = inet_ntoa(ina1.sin_addr); //this is 192.168.4.14
a2 = inet_ntoa(ina2.sin_addr); //this is 10.12.110.57
printf("address 1: %s\n", a1);
printf("address 2: %s\n", a2);
که خروجی آن این خواهد بود:
address 1: 10.12.110.57
address 2: 10.12.110.57
در صورتی که می خواهید مقدار آدرس ها را نگهداری کنید, آنها را در آرایه های مورد نظر خود strcpy() کنید.