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; }