برای استفاده از آدرس IP در اکثر توابع، باید ابتدا IP از شکل رشته ای (شکل نمایشی یا presentation) به شکل Network-Byte-Order تبدیل شود. این تبدیل توسط ()inet_pton انجام می شود.
#include <arpa/inet.h> int inet_pton(int af, const char *src, void *dst);
تعریف struct in_addr به شکل زیر است
typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; // that's a 32-bit int (4 bytes) };
نمونه تبدیل در IPv4 :
// inet_pton-ipv4.c // gcc -std=c99 -o inet_pton-ipv4 inet_pton-ipv4.c #include <stdio.h> #include <arpa/inet.h> int main() { char *ipv4 = "192.168.154.239"; struct in_addr ia; inet_pton(AF_INET, ipv4, &ia); printf("ipv4 string : %s\n", ipv4); printf("sizeof(struct in_addr) : %ld\n", sizeof(struct in_addr)); printf("ia hex : %X\n", ia.s_addr); printf("ia hex : %X\n", ia); printf("ia dec : %u\n", ia.s_addr); printf("ia dec : %u\n", ia); return 0; }
خروجی :
ipv4 string : 192.168.154.239 sizeof(struct in_addr) : 4 ia hex : EF9AA8C0 ia hex : EF9AA8C0 ia dec : 4019890368 ia dec : 4019890368
همانطور که در مثال فوق مشاهده می شود چون struct in_addr فقط یک عضو دارد(s_addr) پس می توان از ia و ia.s_addr به شکل یکسان استفاده کرد.
تفاوت Network-Byte-Order و Host-Byte-Order در خروجی فوق به خوبی دیده میشود چون 192 معادل 0xC0 و 168 معادل 0xA8 و 154 معادل معادل 0x9A و 239 معادل 0xEF است و ضمن ذخیره سازی در حافظه به شکل Little-Endian ذخیره شده (EF9AA8C0)
در تعریف struct in_addr می بینیم که s_addr از نوع uint32_t تعریف شده پس بجای struct in_addr می توان از unsigned int استفاده کرد که روش مناسبی نیست. ولی برای درک بهتر این روش را آزمایش میکنیم :
// inet_pton-ipv4.c // gcc -std=c99 -Wall -Wextra -Werror -pedantic -o inet_pton-ipv4 inet_pton-ipv4.c #include <stdio.h> #include <arpa/inet.h> int main() { char *ipv4 = "192.168.154.239"; unsigned int ui; inet_pton(AF_INET, ipv4, &ui); printf("ipv4 string : %s\n", ipv4); printf("sizeof(unsigned int) : %ld\n", sizeof(unsigned int)); printf("ia hex : %X\n", ui); printf("ia dec : %u\n", ui); return 0; }
خروجی
ipv4 string : 192.168.154.239 sizeof(unsigned int) : 4 ia hex : EF9AA8C0 ia dec : 4019890368
همانطور که در مثال فوق مشاهده میشود، می توان از unsigned int به راحتی به جای struct in_addr استفاده کرد. ترجیح بر این است برای یکپارچگی بین IPv4 و IPv6 از struct in_addr و struct in6_addr استفاده شود. چون IPv6 به شکل یک رشته 16Byte و IPv4 به شکل یک unsigned int که 4Byte است نگهداری می شود.
به دلیل تعریف dst از نوع *void است که می توانیم برخورد چند گانه با آن داشته باشیم (Poor Man's Polymorphism)
نمونه تبدیل در IPv6 :
// inet_pton-ipv6.c // gcc -std=c99 -Wall -Wextra -Werror -pedantic -o inet_pton-ipv6 inet_pton-ipv6.c #include <stdio.h> #include <arpa/inet.h> int main() { char *ipv6 = "0011:2233:4455:6677:8899:AABB:CCDD:EEFF"; struct in6_addr i6a; inet_pton(AF_INET6, ipv6, &i6a); printf("sizeof(struct in6_addr) : %ld\n", sizeof(struct in6_addr)); printf("ipv6 str: %s\n", ipv6); for(long unsigned int i=0; i < sizeof(struct in6_addr); i++) printf("%02X ", i6a.s6_addr[i]); printf("\n"); return 0; }
خروجی :
sizeof(struct in6_addr) : 16 ipv6 str: 0011:2233:4455:6677:8899:AABB:CCDD:EEFF 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
در مثال فوق مشاهده می شود که در IPv6 روش Host-Byte-Oder و Network-Byte-Order یکسان است.