一、前言
前面一口君寫了一篇關于url的文章:《一文帶你理解URI 和 URL 有什么區(qū)別?》
本篇在此基礎上,編寫一個簡單的用于解析url的小例子,
最終目標是解析出URL中所有的數(shù)據(jù)信息。
二、庫函數(shù)
用到的幾個庫函數(shù)如下:
1. strncasecmp
頭文件
#include
函數(shù)定義
intstrncasecmp(constchar*s1,constchar*s2,size_tn);
函數(shù)說明
用來比較參數(shù)s1和s2字符串前n個字符,比較時會自動忽略大小寫的差異。
返回值
若參數(shù)s1和s2字符串相同則返回0。
s1若大于s2則返回大于0的值,
s1若小于s2則返回小于0的值。
2. strstr
頭文件
#include
函數(shù)定義
char*strstr(constchar*str,constchar*substr);
函數(shù)說明
查找 substr 所指的空終止字節(jié)字符串在 str 所指的空終止字節(jié)字符串中的首次出現(xiàn)。不比較空終止字符。
若 str 或 substr 不是指向空終止字節(jié)字符串的指針,則行為未定義。
參數(shù)
str:指向要檢驗的空終止字節(jié)字符串的指針
substr:指向要查找的空終止字節(jié)字符串的指針
返回值
指向于 str 中找到的子串首字符的指針,或若找不到該子串則為空指針。若 substr 指向空字符串,則返回 str 。
3. strtok
函數(shù)定義
char*strtok(char*str,constchar*delim)
功能
分解字符串str為一組字符串,delim為分隔符
參數(shù)
str --要被分解成一組小字符串的字符串。
delim --包含分隔符的 C 字符串。
返回值
該函數(shù)返回被分解的第一個子字符串,如果沒有可檢索的字符串,則返回一個空指針。
4. strncpy
函數(shù)說明
char*strncpy(char*dest,constchar*src,size_tn)
功能
將src指向的字符串拷貝到dest執(zhí)行的內(nèi)存中,最多拷貝n個字符
參數(shù)
dest --指向用于存儲復制內(nèi)容的目標數(shù)組。
src --要復制的字符串。
n --要從源中復制的字符數(shù)。
返回值
該函數(shù)返回最終復制的字符串。
5. inet_pton/inet_ntop
頭文件
#include
#include
#include
函數(shù)聲明
#include
intinet_pton(intfamily,constchar*strptr,void*addrptr);
功能:
將點分十進制的ip地址轉(zhuǎn)化為用于網(wǎng)絡傳輸?shù)臄?shù)值格式
對于IPv4地址和IPv6地址都適用
參數(shù)
family:協(xié)議類型既可以是AF_INET(ipv4)也可以是AF_INET6(ipv6)。如果,以不被支持的地址族作為family參數(shù),這兩個函數(shù)都返回一個錯誤,并將errno置為EAFNOSUPPORT.
strptr:指向點分十進制的IP地址字符串,比如"192.168.1.1"
addrptr:轉(zhuǎn)換結(jié)果存放在addrptr中,比如"192.168.1.1"轉(zhuǎn)換為:0xC0A80101
addrptr類型為:structin_addr
typedefuint32_tin_addr_t;
structin_addr{
in_addr_ts_addr;
};
返回值
若成功則為1,若輸入不是有效的表達式則為0,
若出錯則為-1
constchar*inet_ntop(intfamily,constvoid*addrptr,char*strptr,size_tlen);
功能
將數(shù)值格式轉(zhuǎn)化為點分十進制的ip地址格式,從數(shù)值格式(addrptr)轉(zhuǎn)換到表達式(strptr),
返回值
若成功則為指向結(jié)構(gòu)的指針,若出錯則為NULL
6. gethostbyname
函數(shù)的定義
#include
structhostent*gethostbyname(constchar*hostname);
功能
解析hostname指向的域名,該函數(shù)會將該域名封裝到DNS協(xié)議包中,發(fā)送給DNS服務器,DNS服務器會將該域名對應的地址返回,存儲在structhostent中
參數(shù)
hostname :存儲域名對應的字符串。
返回值
若成功則為非空指針,若出錯則為NULL且設置h_errno
返回的指針類型為:
structhostent{
char*h_name;//officialname
char**h_aliases;//aliaslist
inth_addrtype;//hostaddresstype
inth_length;//addresslenght
char**h_addr_list;//addresslist
}
DNS服務器返回的地址就存儲在該結(jié)構(gòu)體中
三、自定義結(jié)構(gòu)
結(jié)構(gòu)體用于存放需要解析的協(xié)議和端口號
structpro_port{
charpro_s[32];
unsignedshortport;
};
目前本例子只解析以下集中協(xié)議,讀者需要支持其他協(xié)議可以按照該格式增加對應信息即可
#defineHEAD_FTP_P"ftp://"
#defineHEAD_FTPS_P"ftps://"
#defineHEAD_FTPES_P"ftpes://"
#defineHEAD_HTTP_P"http://"
#defineHEAD_HTTPS_P"https://"
#definePORT_FTP21
#definePORT_FTPS_I990//implicit
#definePORT_FTPS_E21//explicit
#definePORT_HTTP80
#definePORT_HTTPS443
structpro_portg_pro_port[]={
{HEAD_FTP_P,PORT_FTP},
{HEAD_FTPS_P,PORT_FTPS_I},
{HEAD_FTPES_P,PORT_FTPS_E},
{HEAD_HTTP_P,PORT_HTTP},
{HEAD_HTTPS_P,PORT_HTTPS},
};
四、程序流程圖
程序流程相對來說,比較簡單,主函數(shù)功能說明如下:
1. parse_url()
intparse_url(char*raw_url,URL_RESULT_T*result)
參數(shù):
raw_url:指向一個url字符串,比如:ftp://peng:pass@baidu.com/dir/index.html
result :url解析后的結(jié)果存放在該結(jié)構(gòu)體中
結(jié)構(gòu)體類型定義如下:
typedefstruct
{
charuser[MAX_USER_LEN];
charpass[MAX_PASS_LEN];
chardomain[INET_DOMAINSTRLEN];//域名
charsvr_dir[MAX_PATH_FILE_LEN];//文件路徑
charsvr_ip[MAX_IP_STR_LEN];
intport;
}URL_RESULT_T;
功能:
解析url字符串,并將解析結(jié)果存放在result中
返回值;
成功返回URL_OK
失敗返回URL_ERROR
2. void remove_quotation_mark()
voidremove_quotation_mark(char*input)
參數(shù)
input:字符串
功能
去掉字符串中的雙引號"
返回值
無
3. parse_domain_dir
intparse_domain_dir(char*url,URL_RESULT_T*result)
參數(shù)
url:執(zhí)行去掉協(xié)議頭的url字符串,比如:peng:pass@baidu.com/dir/index.html
result :url解析后的結(jié)果存放在該結(jié)構(gòu)體中
功能
解析出url中用戶名、密碼、域名/ip、文件路徑等信息
返回值
成功:URL_OK
失?。篣RL_ERROR
4. check_is_ipv4()
intcheck_is_ipv4(char*domain)
參數(shù)
domain:指向一個域名或者IP地址點分十進制字符串,最大長度為:MAX_URL_LEN
功能
判斷domain中存放的是不是合法的IP地址
返回值
1:是IP地址
-1:不是IP地址
5、dns_resoulve()
intdns_resoulve(char*svr_ip,constchar*domain)
參數(shù)
svr_ip:存放DNS協(xié)議解析過的域名對應的IP地址點分十進制字符串
domain:域名字符串
功能
將domain中的域名,通過DNS協(xié)議解析成對應的IP地址
返回值
成功:URL_OK
失?。篣RL_ERROR
五、運行
測試程序
voidmain(void)
{
intret;
charurl_str[256]="ftp://peng:pass@baidu.com/dir/index.html";
parse_url(url_str,&url_result_t);
ret=check_is_ipv4(url_result_t.domain);
if(ret!=1)
{
//dns
dns_resoulve(url_result_t.svr_ip,url_result_t.domain);
}
printf("
-------------result---------------
");
printf("user:%s
",url_result_t.user);
printf("pass:%s
",url_result_t.pass);
printf("port:%d
",url_result_t.port);
printf("domain:%s
",url_result_t.domain);
printf("svr_dir:%s
",url_result_t.svr_dir);
printf("svr_ip:%s
",url_result_t.svr_ip);
printf("-------------end---------------
");
}
執(zhí)行結(jié)果
六、代碼獲取
完整代碼可以進入倉庫獲?。?/p>
https://gitee.com/yikoulinux/url
原文標題:C語言實現(xiàn)url解析小實例
文章出處:【微信公眾號:嵌入式ARM】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
審核編輯:湯梓紅
-
URL
+關注
關注
0文章
138瀏覽量
15218 -
編寫
+關注
關注
0文章
29瀏覽量
8403 -
庫函數(shù)
+關注
關注
0文章
177瀏覽量
33908
原文標題:C語言實現(xiàn)url解析小實例
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論