IPv6 域名解析原理及编程实现

随着 IPv4 资源逐渐耗尽,IPv6 (Internet Protocol version 6) 网络的部署已开始进行,相信已经有不少朋友已经开始使用 v6 的网络了。和 IPv4 最显著的不同是每个 v6 的 IP 地址包含 128 位(16 个字节),相比 v4 来说极大的扩展了地址空间。但是,这也使得 v6 的网络在使用时特别是编程的时候和 v4 的情况不大兼容。本文介绍了针对 IPv6 的 DNS 域名解析知识和编程实现。

由于 DNS 协议的特点,原有的 DNS 系统几乎不需要做什么改变就已经直接支持 IPv6 的域名解析了。有意思的是,客户机并不用接入 v6 的网络甚至根本不需要安装 v6 组件(例如默认的 Windows XP 系统)就可以请求解析 v6 的地址,只需要系统可以与一个有效的 DNS 服务器建立连接(例如通过 DHCP 自动获取的 DNS 服务器),而无论这个 DNS 服务器是 v6 还是 v4 的。事实上,解析 v6 地址与 v4 唯一的不同就是 v4 查询域名的 A 记录而 v6 查询域名的 AAAA 记录。

下面的例子演示了如何通过 Windows 的 nslookup 命令和 BIND 中的 dig 命令查询 gipv6.aulddays.com 这个 IPv6 域名的方法(注意,使用的 OpenDNS 服务器 208.67.222.222 就是通过 IPv4 连接的):

>nslookup -querytype=AAAA gipv6.aulddays.com
Server:  resolver
Address:1.opendns.com  208.67.222.222

Non-authoritative answer:
Name:    gipv6.aulddays.com
Address:  2001:4860:b004::68
>dig AAAA gipv6.aulddays.com

; <<>> DiG 9.4.2 <<>> AAAA gipv6.aulddays.com
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 943
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;gipv6.aulddays.com. IN AAAA

;; ANSWER SECTION:
gipv6.aulddays.com. 1800 IN AAAA 2001:4860:b004::68

;; Query time: 360 msec
;; SERVER: 208.67.222.222#53(208.67.222.222)
;; WHEN: Sat Sep 19 16:13:18 2009
;; MSG SIZE rcvd: 64

下面说说如何在程序中解析 IPv6 的域名。传统的 v4 地址是使用 gethostbyname() 函数解析,虽然可以通过修改编译选项的方式强制它工作在 v6 状态,但这样也失去了兼容性。为此,最好使用更新的 getaddrinfo() 函数,该函数同时支持 v4 和 v6 域名的解析,VC++ 中的示例代码如下:

#include "stdio.h"
#include "Ws2tcpip.h"

#pragma comment(lib, "Ws2_32.lib")  // getaddrinfo 需要的 lib

int main(int argc, char * argv[])
{
    const char *strDomain2Resolve = "gipv6.aulddays.com";

    // 初始化 Winsock
    WSADATA wsaData;
    int nStatus = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (NO_ERROR != nStatus)
    {
        printf("WSAStartup() 错误\n");
        return -1;
    }

    addrinfo Hints, *AddrList;
    memset(&Hints, 0, sizeof(Hints));
    Hints.ai_family = PF_INET6; // IPv6 address family

    // 进行域名解析
    nStatus = getaddrinfo(strDomain2Resolve, NULL, &Hints, &AddrList);
    if (NO_ERROR != nStatus)
    {
        // 处理出错的情况,
        // 例如目标域名没有对应的 AAAA 记录
        printf("getaddrinfo() 失败,错误信息为 %d: %s\n",
            nStatus, gai_strerror(nStatus));
        return -1;
    }

    // 打印所有找到的地址(一个域名可能对应多个 IP 地址)
    printf("已解析出下列地址:\n");
    char pBuf[64];  // 打印缓冲
    for(addrinfo *i = AddrList; i; i = i->ai_next)
    {
        // 取得一个解析出的地址
        in6_addr DnsAddr = ((sockaddr_in6 *)i->ai_addr)->sin6_addr;
        // 得到可打印版本
        inet_ntop(AF_INET6, &DnsAddr, pBuf, 64);
        printf("%s\n", pBuf);
    }

    // 一般来说,客户端程序使用解析出的 IP 列表中的第一个即可
    // (如果解析出多个地址的话)
    in6_addr AddrToUse = ((sockaddr_in6 *)AddrList->ai_addr)->sin6_addr;

    freeaddrinfo(AddrList);

    WSACleanup();
}

查看:原文地址;来源:live.aulddays.com

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值