基于Linux,URL解析以及获取域名的IP地址。

int http_parse_url(http_dest_t *dest, const char *url)
{
    char        *d;
    const char  *p, *q;
    const char  *uri;
    int i;

    uri = url;

    if ((p = strstr(url, "://"))) {
        snprintf(dest->scheme, URL_SCHEME_LEN + 1, "%.*s", (int)(p - uri), uri);
        uri =  p + 3;
    } else {
        p = uri;
        strcpy(dest->scheme, "http");
    }
    if (!*uri || *uri == '/' || *uri == '.')
        goto nohost;

    p = strpbrk(uri, "/@");
    if (p && *p == '@') {
        /* username */
        for (q = uri, i = 0; (*q != ':') && (*q != '@'); q++)
            if (i < URL_USER_LEN) {
                dest->user[i++] = *q;
            }
        /* password */
        if (*q == ':')
            for (q++, i = 0; (*q != ':') && (*q != '@'); q++)
                if (i < URL_PWD_LEN) {
                    dest->password[i++] = *q;
                }

        p++;
    } else {
        p = uri;
    }

    memset(dest->host, 0, MAX_HOST_NAME_LEN+1);
    for (i = 0; *p && (*p != '/') && (*p != ':'); p++) {
        if (i < MAX_HOST_NAME_LEN){
            dest->host[i++] = *p;
        }
    }
       
    /* port */
    if(strncmp(url, "https:", 6) == 0) {
        dest->port = 443;    
    } else {
        dest->port = 80;
    }
    if (*p == ':') {
        dest->port = 0;
        for (q = ++p; *q && (*q != '/'); q++)
            if (isdigit(*q)) {
                dest->port = dest->port * 10 + (*q - '0');
            } else {
                /* invalid port */
                return -1;
            }
        p = q;
    }
nohost:
    if (!*p)
        p = "/";
    if (strcasecmp(dest->scheme, "http") == 0 ||
        strcasecmp(dest->scheme, "https") == 0) {
        const char hexnums[] = "0123456789abcdef";
        d = dest->uri;
        while (*p != '\0') {
            if (!isspace(*p)) {
                *d++ = *p++;
            } else {
                *d++ = '%';
                *d++ = hexnums[((unsigned int)*p) >> 4];
                *d++ = hexnums[((unsigned int)*p) & 0xf];
                p++;
            }
        }
        *d = '\0';
    }
    return 0;
}

以上代码解析出URL包含的信息,其结构体为:

typedef struct http_dest_t {
    char scheme[URL_SCHEME_LEN];
    char host[MAX_HOST_NAME_LEN];
    char uri[MAX_URI_LEN];

    char    user[URL_USER_LEN+1];
    char    password[URL_PWD_LEN+1];

    int     port;
}http_dest_t;

如下函数解析域名的ip地址。支持IPV6与IPV4

int util_resolv_domain_name(const char* domain_name,char* ipv4_addr,char* ipv6_addr,int* result_ind)
{
    struct addrinfo *answer,hints,*addr_info_p;
    int ret;
    struct sockaddr_in *sinp4;
    struct sockaddr_in6 *sinp6;
    char* addr;

    if( result_ind )
    {
        *result_ind=0;
    }

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    /*
     * The getaddrinfo() function allocates and initializes a linked list of addrinfo structures, one for each network address that matches node  and  service,  subject  to  any
       restrictions imposed by hints, and returns a pointer to the start of the list in res.  The items in the linked list are linked by the ai_next field.
     * */
    ret = getaddrinfo(domain_name, NULL, &hints, &answer);
    if ( !ret ) {
        for (addr_info_p = answer; addr_info_p != NULL; addr_info_p = addr_info_p->ai_next) {
            if(addr_info_p->ai_family == AF_INET) {
                sinp4 = (struct sockaddr_in *)addr_info_p->ai_addr;
                /*
                 * The  inet_ntoa()  function  converts  the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation.  The string is returned in a
                            statically allocated buffer, which subsequent calls will overwrite.
                 * */
                addr = inet_ntoa( sinp4->sin_addr);
                if( ipv4_addr ) {
                    strcpy(ipv4_addr,addr);
                }
                if( result_ind ) {
                    *result_ind=(*result_ind)|IPv4_EXIST_FLAG;
                }
            } else if(addr_info_p->ai_family == AF_INET6) {
                sinp6 = (struct sockaddr_in6 *)addr_info_p->ai_addr;
                if( ipv6_addr ) {
                    sprintf(ipv6_addr
                            ,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
                            ,sinp6->sin6_addr.s6_addr[0]
                            ,sinp6->sin6_addr.s6_addr[1]
                            ,sinp6->sin6_addr.s6_addr[2]
                            ,sinp6->sin6_addr.s6_addr[3]
                            ,sinp6->sin6_addr.s6_addr[4]
                            ,sinp6->sin6_addr.s6_addr[5]
                            ,sinp6->sin6_addr.s6_addr[6]
                            ,sinp6->sin6_addr.s6_addr[7]
                            ,sinp6->sin6_addr.s6_addr[8]
                            ,sinp6->sin6_addr.s6_addr[9]
                            ,sinp6->sin6_addr.s6_addr[10]
                            ,sinp6->sin6_addr.s6_addr[11]
                            ,sinp6->sin6_addr.s6_addr[12]
                            ,sinp6->sin6_addr.s6_addr[13]
                            ,sinp6->sin6_addr.s6_addr[14]
                            ,sinp6->sin6_addr.s6_addr[15]
                            );
                }
                if( result_ind ) {
                    *result_ind=(*result_ind)|IPv6_EXIST_FLAG;
                }
            }
        }
        freeaddrinfo(answer);
    } else {
        return -1;
    }
    return 0;
}

 

posted @ 2017-06-23 15:55  Prefog  阅读(3956)  评论(0编辑  收藏  举报