Linux下c实现域名转IP的方法封装

arm开发板下运行时请确认你的开发板已联网
cat /etc/resolv.conf是否为空

urlIpTest_main.c


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>    //
#include <netdb.h>      // gethostbyname, gethostbyname2, gethostbyname_r, gethostbyname_r2
#include <setjmp.h>
#include <errno.h>

#include <fcntl.h>      // 非阻塞关键字
#include <stdbool.h>    // 使用bool变量
#include <pthread.h>    // 使用多线程

void delayus(unsigned int us)
{
    struct timeval tim;
    tim.tv_sec = us/1000000;
    tim.tv_usec = us%1000000;
    select(0, NULL, NULL, NULL, &tim);
}

////////////////////////////////// 域名转IP ////////////////////////////////// 

// 封装个和线程交互用的结构体
typedef struct{
    pthread_t thread_id;
    char ip[256];
    bool result;
    bool actionEnd;
}GetHostName_Struct;

// 调用 gethostbyname_r 函数需在单独的线程中调用, 阻塞时还可以外部超时退出
void *getHost_fun(void *arge)
{
    int ret;
    int i;
    char buf[1024];
    struct hostent host_body, *host;
    struct in_addr **addr_list;
    GetHostName_Struct *gs = (GetHostName_Struct *)arge;

    /*  此类方法不可重入!  即使关闭线程
    if((host = gethostbyname(gs->ip)) == NULL)
    //if((host = gethostbyname2(gs->ip, AF_INET)) == NULL)
    {
        gs->actionEnd = true;
        return NULL;
    }*/
    if(gethostbyname_r(gs->ip, &host_body, buf, sizeof(buf), &host, &ret))
    {
        gs->actionEnd = true;
        return NULL;
    }

    if(host == NULL)
    {
        gs->actionEnd = true;
        return NULL;
    }
    addr_list = (struct in_addr **)host->h_addr_list;

    // 查看获得的ip列表
    /*printf("ip name : %s\r\nip list : ", host->h_name);
    for(i = 0; addr_list[i] != NULL; i++) 
        printf("%s, ", inet_ntoa(*addr_list[i])); 
    printf("\r\n");*/

    // 默认返回列表第一条ip
    if(addr_list[0] == NULL)
    {
        gs->actionEnd = true;
        return NULL;
    }
    memset(gs->ip, 0, sizeof(gs->ip));
    strcpy(gs->ip, (char *)inet_ntoa(*addr_list[0]));
    gs->result = true;
    gs->actionEnd = true;
    return NULL;
}

// 封装方法, 成功返回调用耗时, 错误返回负数的耗时  (ms)
int getIpFromHostName(char *hostName, char *backIp)
{
    int i, timeOut = 1;
     GetHostName_Struct gs;
    if(hostName == NULL)
        return -1;
    else if(strlen(hostName) < 1)
        return -1;
    //----- 开线程从域名获取IP -----
    memset(&gs, 0, sizeof(GetHostName_Struct));
    strcpy(gs.ip, hostName);
    gs.result = false;
    gs.actionEnd = false;
    if (pthread_create(&gs.thread_id, NULL, getHost_fun, &gs) < 0)
        return -1;
    i = 0;
    while(!gs.actionEnd)
    {
        if(++i > 10)
        {
            i = 0;
            if(++timeOut > 1000)    // 1s 超时
                break;
        }
        delayus(1000);// 1ms延时
    }
    //pthread_cancel(gs.thread_id);//必须让系统跑完,否则内存不能释放
    pthread_join(gs.thread_id, NULL);
    if(!gs.result)
        return -timeOut;
    //----- 开线程从域名获取IP -----
    memset(backIp, 0, strlen(backIp));
    strcpy(backIp, gs.ip);
    return timeOut;
}

////////////////////////////////// 域名转IP ////////////////////////////////// 

int main(int argc, char *argv[])
{
    char ip[128] = {0};
    int ret;
    //
    if(argc < 2)
    {
        printf("input such as : ./urlIpTest www.baidu.com\r\n");
        return 0;
    }
    //
    if((ret = getIpFromHostName(argv[1], ip)) > 0)
        printf("host(%s) to ip(%s) , ret/%d\r\n", argv[1], ip, ret);
    else
        printf("test failed , ret/%d\r\n", ret);
    //
    return 0;
}

// 在tcp连接时的使用
/*
...
{
    ...
    struct sockaddr_in sock_addr;

    memset(&sock_addr,0,sizeof(sock_addr));

    sock_addr.sin_family=AF_INET;
    //获取IP不成功时可尝试调用域名转换

    if((sock_addr.sin_addr.s_addr = inet_addr(ip)) == INADDR_NONE)

    {

        //printf("url is : %s\r\n", ip);

        //

        memset(buf, 0, sizeof(buf));

        ret = getIpFromHostName(ip, buf);

        if(ret < 0)

            return ret;

        else if(strlen(buf) < 7)

            return -ret;

        //

        if((sock_addr.sin_addr.s_addr = inet_addr(buf)) == INADDR_NONE)

            return -ret;

        printf("Host(%s) to Ip(%s)\r\n", ip, buf);

    }
    ...
}
*/

Makefile:

#CC=arm-linux-gnueabihf-
CC=
target:
    $(CC)gcc -O3 -o urlIpTest urlIpTest_main.c -lpthread
clean:
    @rm -rf urlIpTest
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值