這次是要在linux下將ipv4的程式改成ipv4/ipv6相容的程式。
原文可以看Porting applications to IPv6 HowTo。
首先利用sockaddr_storage取代傳統的sockaddr_in。當使用ipv4做溝通時,就將這個struct轉為sockaddr_in,使用ipv6溝通時,就要轉換為sockaddr_in6。sockaddr_storage裏面構造長得很像sockaddr_in和sockaddr_in6。
#if ULONG_MAX > 0xffffffff
# define __ss_aligntype __uint64_t
#else
# define __ss_aligntype __uint32_t
#endif
#define _SS_SIZE 128
#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))
struct sockaddr_storage
{
sa_family_t ss_family; /* Address family */
__ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
};
當我要使用的時候,我可以預先做轉好的動作備用。
struct sockaddr_storage sa;
struct sockaddr_in *sa_v4 = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sa_v6 = (struct sockaddr_in *)&sa;
或是你需要用的時候再做轉換。
(((struct sockaddr_in *)&sa)->sin_addr.s_addr) --->v4
(((struct sockaddr_in6 *)&sa)->sin6_addr.s6_addr) --->v6
接著,記得系統要build好ipv6的module,那樣的話,bind, recv這些通訊方法通通不用改。
而要分辨現在溝通模式是v4還是v6,可以看ss_family。
if(sa.ss_family == AF_INET){
...
}else if(sa.ss_family == AF_INET6){
...
}
最後就要有耐心的補完v6的邏輯。因為網路位址轉字串,位址比較都和v4不相同。詳細範例可以再看前面提到的Porting applications to IPv6 HowTo。
沒有留言:
張貼留言