C를 사용하여 URL을 구문 분석하는 가장 좋은 방법은 무엇입니까?
다음과 같은 URL이 있습니다.
http://192.168.0.1:8080/servlet/rece
URL을 구문 분석하여 값을 가져옵니다.
IP: 192.168.0.1
Port: 8080
page: /servlet/rece
그걸 어떻게 하는 거죠?
개인적으로, 저는 그것을 훔칩니다.HTParse.c
모듈을 사용할 수 있습니다(예: 스라소니 웹 브라우저에서 사용됨).그러면 다음과 같은 작업을 수행할 수 있습니다.
strncpy(hostname, HTParse(url, "", PARSE_HOST), size)
잘 설정되고 디버깅된 라이브러리를 사용할 때 중요한 점은 URL 구문 분석의 일반적인 트랩(예: 호스트가 IP 주소인 경우, 특히 IPv6 주소인 경우 많은 정규식이 실패함)에 빠지지 않는다는 것입니다.
저는 sscanf를 사용하여 간단한 코드를 작성했는데, 이것은 매우 기본적인 URL을 구문 분석할 수 있습니다.
#include <stdio.h>
int main(void)
{
const char text[] = "http://192.168.0.2:8888/servlet/rece";
char ip[100];
int port = 80;
char page[100];
sscanf(text, "http://%99[^:]:%99d/%99[^\n]", ip, &port, page);
printf("ip = \"%s\"\n", ip);
printf("port = \"%d\"\n", port);
printf("page = \"%s\"\n", page);
return 0;
}
./urlparse
ip = "192.168.0.2"
port = "8888"
page = "servlet/rece"
늦을지도...제가 사용한 것은 -입니다.http_parser_parse_url()
Joyent/HTTP parser lib에서 분리된 기능과 필요한 매크로 - 잘 작동했습니다.~600
LOC.
쉬운 방법을 원한다면 정규 표현으로.그렇지 않으면 FLEX/BISON을 사용합니다.
URI 구문 분석 라이브러리를 사용할 수도 있습니다.
Libcurl은 이제curl_url_get()
호스트, 경로 등을 추출할 수 있는 함수
코드 예제: https://curl.haxx.se/libcurl/c/parseurl.html
/* extract host name from the parsed URL */
uc = curl_url_get(h, CURLUPART_HOST, &host, 0);
if(!uc) {
printf("Host name: %s\n", host);
curl_free(host);
}
이 파일은 크기를 줄이고 http://draft.scyphus.co.jp/lang/c/url_parser.html 에 매우 적합합니다. 단 두 개의 파일(*.c, *.h).
코드 [1]을 수정해야 했습니다.
모든 함수 호출을 http_parsed_url_free(purl)에서 parsed_url_free(purl)로 변경합니다.
//Rename the function called
//http_parsed_url_free(purl);
parsed_url_free(purl);
순수하다sscanf()
기반 솔루션:
//Code
#include <stdio.h>
int
main (int argc, char *argv[])
{
char *uri = "http://192.168.0.1:8080/servlet/rece";
char ip_addr[12], path[100];
int port;
int uri_scan_status = sscanf(uri, "%*[^:]%*[:/]%[^:]:%d%s", ip_addr, &port, path);
printf("[info] URI scan status : %d\n", uri_scan_status);
if( uri_scan_status == 3 )
{
printf("[info] IP Address : '%s'\n", ip_addr);
printf("[info] Port: '%d'\n", port);
printf("[info] Path : '%s'\n", path);
}
return 0;
}
그러나 이 솔루션은 다음을 위해 맞춤형으로 제작되었습니다.[protocol_name]://[ip_address]:[port][/path]
URI 유형입니다.URI 구문에 있는 구성 요소에 대한 자세한 내용은 RFC 3986으로 이동하면 됩니다.
이제 맞춤 제작 형식 문자열을 분석해 보겠습니다."%*[^:]%*[:/]%[^:]:%d%s"
%*[^:]
프로토콜/프로토콜을 무시하는 데 도움이 됩니다(예:http, https, ftp 등)그것은 기본적으로 처음부터 그것이 만날 때까지 문자열을 캡처합니다.
:
처음으로 등장하는 캐릭터.그리고 우리가 사용한 이후로*
의 직후에%
문자이므로 캡처된 문자열은 무시됩니다.%*[:/]
프로토콜과 IP 주소 사이에 있는 구분자를 무시하는 데 도움이 됩니다.://
%[^:]
구분 기호 뒤에 있는 문자열이 발생할 때까지 캡처하는 데 도움이 됩니다.:
그리고 이 캡처된 문자열은 IP 주소일 뿐입니다.:%d
바로 뒤에 앉아 있는 번호를 잡는 데 도움이 됩니다.:
문자(IP 주소를 캡처하는 동안 발견된 문자)입니다.여기에 캡처된 번호는 기본적으로 당신의 포트 번호입니다.%s
아시다시피, 에서는 찾고 있는 리소스의 경로일 뿐인 나머지 문자열을 캡처하는 데 도움이 됩니다.
이 Crist는 유용할 수 있습니다.sscanf로 순수 C 솔루션을 구현합니다.
https://github.com/luismartingil/per.scripts/tree/master/c_parse_http_url
그것은 사용합니다.
// Parsing the tmp_source char*
if (sscanf(tmp_source, "http://%99[^:]:%i/%199[^\n]", ip, &port, page) == 3) { succ_parsing = 1;}
else if (sscanf(tmp_source, "http://%99[^/]/%199[^\n]", ip, page) == 2) { succ_parsing = 1;}
else if (sscanf(tmp_source, "http://%99[^:]:%i[^\n]", ip, &port) == 2) { succ_parsing = 1;}
else if (sscanf(tmp_source, "http://%99[^\n]", ip) == 1) { succ_parsing = 1;}
(...)
나는 이것을 썼습니다.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct
{
const char* protocol = 0;
const char* site = 0;
const char* port = 0;
const char* path = 0;
} URL_INFO;
URL_INFO* split_url(URL_INFO* info, const char* url)
{
if (!info || !url)
return NULL;
info->protocol = strtok(strcpy((char*)malloc(strlen(url)+1), url), "://");
info->site = strstr(url, "://");
if (info->site)
{
info->site += 3;
char* site_port_path = strcpy((char*)calloc(1, strlen(info->site) + 1), info->site);
info->site = strtok(site_port_path, ":");
info->site = strtok(site_port_path, "/");
}
else
{
char* site_port_path = strcpy((char*)calloc(1, strlen(url) + 1), url);
info->site = strtok(site_port_path, ":");
info->site = strtok(site_port_path, "/");
}
char* URL = strcpy((char*)malloc(strlen(url) + 1), url);
info->port = strstr(URL + 6, ":");
char* port_path = 0;
char* port_path_copy = 0;
if (info->port && isdigit(*(port_path = (char*)info->port + 1)))
{
port_path_copy = strcpy((char*)malloc(strlen(port_path) + 1), port_path);
char * r = strtok(port_path, "/");
if (r)
info->port = r;
else
info->port = port_path;
}
else
info->port = "80";
if (port_path_copy)
info->path = port_path_copy + strlen(info->port ? info->port : "");
else
{
char* path = strstr(URL + 8, "/");
info->path = path ? path : "/";
}
int r = strcmp(info->protocol, info->site) == 0;
if (r && info->port == "80")
info->protocol = "http";
else if (r)
info->protocol = "tcp";
return info;
}
시험
int main()
{
URL_INFO info;
split_url(&info, "ftp://192.168.0.1:8080/servlet/rece");
printf("Protocol: %s\nSite: %s\nPort: %s\nPath: %s\n", info.protocol, info.site, info.port, info.path);
return 0;
}
나가.
Protocol: ftp
Site: 192.168.0.1
Port: 8080
Path: /servlet/rece
중 사를 지 작 문 용 바 파 정 나 함 자 기 구 ' :'를 사용합니다.sscanf()
.
언급URL : https://stackoverflow.com/questions/726122/best-ways-of-parsing-a-url-using-c
'bestsource' 카테고리의 다른 글
Oracle에서 두 날짜 사이의 일 수(날짜 포함)를 가져옵니다. (0) | 2023.07.23 |
---|---|
C 함수로 셸 내장 명령을 실행하려면 어떻게 해야 합니까? (0) | 2023.07.23 |
구조물 시간 지정 형식 지정 (0) | 2023.07.23 |
Backbone.js에서 하위 뷰를 초기화하고 렌더링하는 방법은 무엇입니까? (0) | 2023.07.23 |
한 데이터베이스/테이블에서 다른 데이터베이스/테이블로 데이터를 복사하는 방법 (0) | 2023.07.23 |