在IPV6大勢所趨下,我們不得不考慮擴充現有的程式,讓它也支援ipv6。本篇主要針對socket下ipv4到ipv6的移植相關內容。
一、區別之處
1)地址結構
ipv4地址結構:
struct sockaddr_in {
short int sin_family; //地址族
unsigned short int sin_port; //連接埠號碼
struct in_addr sin_addr; //地址
unsigned char sin_zero[8];
};
struct in_addr {
unsigned long s_addr;
};
ipv6地址結構:
struct sockaddr_in6{
uint8_t sin6_len; //IPv6 為固定的(9php.com)24 位元組長度
sa_family_t sin6_family; //地址簇類型,為AF_INET6
in_port_t sin6_port; //16 位連接埠號碼,網路位元組序
uint32_t sin6_flowinfo; //32 位流標籤
struct in6_addr sin6_addr; //128 位IP 位址
}
舉例:
ipv4地址賦值:
rcv_udp_addr.sin_family = AF_INET;
rcv_udp_addr.sin_addr.s_addr = htonl(INADDR_ANY);
rcv_udp_addr.sin_port = htons(UDPRCV_PORT);
ipv6地址賦值:
rcv_udp_addr.sin6_family = PF_INET6;
rcv_udp_addr.sin6_addr = in6addr_any;
rcv_udp_addr.sin6_port = htons(UDPRCV_PORT);
注意那個ipv4的INADDR_ANY是主機位元組序,而in6addr_any為網路位元組序
2)socket建立
int socket(int domain, int type, int protocol);
差別在於ipv4時,第一個參數為AF_INET,而ipv6時,第一個參數為AF_INET6
sock_tcp = socket(AF_INET, SOCK_STREAM, 0)//ipv4
sock_tcp = socket(PF_INET6, SOCK_STREAM, 0)//ipv6
3)字串地址和網路序ip地址的相互轉換:
ipv4中字串地址轉換為網路序ip地址使用函數inet_aton,而ipv6使用inet_pton
int inet_aton(const char *cp, struct in_addr *inp);
int inet_pton(int af, const char *src, void *dst);
例:
inet_pton(AF_INET6, hostname, &snd_tcp_addr.sin6_addr)
其中hostname為c類型字串ip地址
相反的轉換ipv4使用inet_ntoa,而ipv6使用inet_ntop
char *inet_ntoa(struct in_addr in);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
例:
inet_ntop(PF_INET6,&rcv_udp_addr.sin6_addr,ip,sizeof(ip));
其中ip為c風格字串
4)主機名稱和地址的轉換
ipv4使用gethostbyname和gethostbyaddr
而通用採用的是getaddrinfo和getnameinfo
例:
getaddrinfo(ipaddr, port,&hints,&res);
使用ipv6需要包含:
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
一個例子
char IPdotdec[20]; //存放點分十進位IP地址
struct in_addr s; // IPv4地址結構體
int main (void)
{
// 輸入IP地址
printf("Please input IP address: ");
scanf("%s", &IPdotdec);
// 轉換
inet_pton(AF_INET, IPdotdec, (void *)&s);
printf("inet_pton: 0x%x/n", s.s_addr); // 注意得到的位元組序
// 反轉換
inet_ntop(AF_INET, (void *)&s, IPdotdec, 16);
printf("inet_ntop: %s/n", IPdotdec);
}