浅墨浓香

想要天亮进城,就得天黑赶路。

导航

第14章 UDP编程(2)_端口绑定和域名解析

Posted on 2017-04-06 14:22  浅墨浓香  阅读(832)  评论(0编辑  收藏  举报

2. 端口绑定和域名解析

2.1 端口绑定:SO_REUSEADDR选项

int opt = 1;//1表示启用该选项
//设置为可重新使用端口,每次启动该端口时,会重新绑定端口。相当于端口被复位并被重新。
//绑定。因此,以后以最后这次绑定为准
if((ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){
    perror("setsockopt error");
    exit(1);
}

2.2 域名解析

(1)域名解析过程

 

(2)域名解析函数

头文件

#include <netdb.h>

函数

struct hostent* gethostent(void);

struct hostent* gethostbyname(const char* hostname);

void sethostent(int stayopen);

void endhostent(void);  //注意get和endhostent应成对使用!

参数

struct hostent{
    char*  h_name;     //正式主机名
    char** h_aliases;  //别名,字符串数组
    int    h_addrtype; //协议类型
    int    h_length;   //网络地址大小
    char** h_addr_list;//指向网络地址的指针
};

功能

域名解析

备注

查看域名和IP映射关系:#more /etc/hosts

(3)hostent结构体 

(4)域名解析案例

//域名解析,并将结果保存在hostent结构体中
if((hptr = gethostbyname("www.google.com")) == NULL){
    fprintf(stderr, "gethostbyname call failed.%s\n", 
                    hstrerror(h_errno));
    return -1;
}

printf("official name: %s\n", hptr->h_name); //输出正式名
for(pptr = hptr->h_aliases; *pptr != NULL; pptr++){ //输出对应各个别名
    printf("\t alias: %s\n", *pptr);
}

if(hptr->h_addrtype != AF_INET){   //判断是否为IPv4地址
    fprintf(stderr, "Invalid address type %d\n", hptr->addrtype);
    return -1;
}

pptr = hptr->h_addr_list;
for(; *pptr != NULL; pptr++){    //输出点分十进制的IP地址(字符串)
    printf("\t address: %s\n", 
               inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
}

【编程实验】根据域名解析出IP地址

//gethost.c

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

int is_host(struct hostent* host, char* name)
{
    //如果正式名为name,则直接返回
    if(!strcmp(host->h_name, name)) return 1;

    //查找别名为name
    int i = 0;
    while(host->h_aliases[i] != NULL){
        if(!strcmp(host->h_aliases[i], name)) return 1;
        i++;
    }
}

//根据主机名获取IP
unsigned int get_ip_by_name(char* name)
{
    unsigned int ip = 0;
    struct hostent* host;
    //遍历/etc/hosts文件,找出所有的主机名。
    //每调用一次gethostent将读取文件的一行(对应一个主机)
    while((host = gethostent()) != NULL){
        if(is_host(host, name)){
            //h_addr_list[0]中所存放在IP是网络字节序,共4个字节。
            memcpy(&ip, host->h_addr_list[0], 4);
            break;
        }
    }
    endhostent();
    return ip;
}

void out_addr(struct hostent* h)
{
    printf("hostname: %s\n", h->h_name);
    printf("addrtype: %s\n", h->h_addrtype == AF_INET ? "IPv4": "IPv6");

    char ip[16];
    memset(ip, 0, sizeof(ip));
    inet_ntop(h->h_addrtype, h->h_addr_list[0], ip, sizeof(ip));//绑定的第1个IP地址
    printf("ip address: %s\n", ip);

    //别名
    int i = 0;
    while(h->h_aliases[i] != NULL){
        printf("aliases: %s\n", h->h_aliases[i]);
        i++;
    }
}

int main(int argc, char* argv[])
{
    if(argc < 2){
        printf("usage: %s host\n", argv[0]);
        exit(1);
    }

    struct hostent* h;
    h = gethostbyname(argv[1]);

    if(h != NULL){
        out_addr(h);
    }else{
        printf("no %s exist\n", argv[1]);
    }

    //根据主机名,输出IP
    unsigned int ipNet = get_ip_by_name(argv[1]); //网络字节序IP
    char ip[16];
    memset(ip, 0, sizeof(ip));
    inet_ntop(AF_INET, &ipNet, ip, sizeof(ip));//绑定的第1个IP地址
    printf("ip address: %s\n", ip);

    return 0;
}
/*host文件
 * [root@localhost 14.udp]# more /etc/hosts
 * 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
 * 192.168.32.100 santaclaus www.5iedu.com
 * ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
 *
 *输出结果
 [root@localhost 14.udp]# bin/gethost santaclaus
 hostname: santaclaus
 addrtype: IPv4
 ip address: 192.168.32.100
 aliases: www.5iedu.com
 ip address: 192.168.32.100
 [root@localhost 14.udp]# bin/gethost www.5iedu.com
 hostname: santaclaus
 addrtype: IPv4
 ip address: 192.168.32.100
 aliases: www.5iedu.com
 ip address: 192.168.32.100
 [root@localhost 14.udp]# bin/gethost localhost    
 hostname: localhost
 addrtype: IPv4
 ip address: 127.0.0.1
 aliases: localhost.localdomain
 aliases: localhost4
 aliases: localhost4.localdomain4
 aliases: localhost.localdomain
 aliases: localhost6
 aliases: localhost6.localdomain6
 ip address: 127.0.0.1
 */