一、前言 前面一口君写了一篇关于url的文章:《一文带你理解uri 和 url 有什么区别?》
本篇在此基础上,编写一个简单的用于解析url的小例子,
最终目标是解析出url中所有的数据信息。
二、库函数 用到的几个库函数如下:
1. strncasecmp 头文件
#include 函数定义
int strncasecmp(const char *s1,const char *s2,size_t n); 函数说明
用来比较参数s1和s2字符串前n个字符,比较时会自动忽略大小写的差异。 返回值
若参数s1和s2 字符串相同则返回0。s1 若大于s2则返回大于0的值,s1若小于s2则返回小于0 的值。 2. strstr 头文件
#include 函数定义
char *strstr( const char* str, const char* substr ); 函数说明
查找 substr 所指的空终止字节字符串在 str 所指的空终止字节字符串中的首次出现。不比较空终止字符。若 str 或 substr 不是指向空终止字节字符串的指针,则行为未定义。 参数
str :指向要检验的空终止字节字符串的指针substr :指向要查找的空终止字节字符串的指针 返回值
指向于 str 中找到的子串首字符的指针,或若找不到该子串则为空指针。若 substr 指向空字符串,则返回 str 。 3. strtok 函数定义
char *strtok(char *str, const char *delim) 功能
分解字符串 str 为一组字符串,delim 为分隔符 参数
str -- 要被分解成一组小字符串的字符串。delim -- 包含分隔符的 c 字符串。 返回值
该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。 4. strncpy 函数说明
char *strncpy(char *dest, const char *src, size_t n) 功能
将src指向的字符串拷贝到dest执行的内存中,最多拷贝n个字符 参数
dest -- 指向用于存储复制内容的目标数组。src -- 要复制的字符串。n -- 要从源中复制的字符数。 返回值
该函数返回最终复制的字符串。 5. inet_pton/inet_ntop 头文件
#include #include #include 函数声明
#include int inet_pton(int family, const char *strptr, void *addrptr); 功能:
将点分十进制的ip地址转化为用于网络传输的数值格式对于ipv4地址和ipv6地址都适用 参数
family:协议类型既可以是af_inet(ipv4)也可以是af_inet6(ipv6)。如果,以不被支持的地址族作为family参数,这两个函数都返回一个错误,并将errno置为eafnosupport.strptr:指向点分十进制的ip地址字符串,比如192.168.1.1addrptr:转换结果存放在addrptr中,比如192.168.1.1转换为:0xc0a80101addrptr类型为:struct in_addr typedef uint32_t in_addr_t;struct in_addr { in_addr_t s_addr;}; 返回值
若成功则为1,若输入不是有效的表达式则为0,若出错则为-1 const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len); 功能
将数值格式转化为点分十进制的ip地址格式,从数值格式(addrptr)转换到表达式(strptr), 返回值
若成功则为指向结构的指针,若出错则为null 6. gethostbyname 函数的定义
#include struct hostent * gethostbyname(const char * hostname); 功能
解析hostname指向的域名,该函数会将该域名封装到dns协议包中,发送给dns服务器,dns服务器会将该域名对应的地址返回,存储在struct hostent中 参数
hostname :存储域名对应的字符串。 返回值
若成功则为非空指针,若出错则为null且设置h_errno返回的指针类型为:struct hostent{ char *h_name; //official name char **h_aliases; //alias list int h_addrtype; //host address type int h_length; //address lenght char **h_addr_list; //address list}dns服务器返回的地址就存储在该结构体中 三、自定义结构 结构体用于存放需要解析的协议和端口号
struct pro_port{ char pro_s[32]; unsigned short port;}; 目前本例子只解析以下集中协议,读者需要支持其他协议可以按照该格式增加对应信息即可
#define head_ftp_p ftp://#define head_ftps_p ftps:// #define head_ftpes_p ftpes://#define head_http_p http://#define head_https_p https://#define port_ftp 21#define port_ftps_i 990 //implicit#define port_ftps_e 21 //explicit#define port_http 80#define port_https 443struct pro_port g_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},}; 四、程序流程图
程序流程相对来说,比较简单,主函数功能说明如下:
1. parse_url() int parse_url(char *raw_url,url_result_t *result) 参数:
raw_url:指向一个url字符串,比如:ftp://peng:pass@baidu.com/dir/index.htmlresult :url解析后的结果存放在该结构体中结构体类型定义如下:typedef struct{ char user[max_user_len]; char pass[max_pass_len]; char domain[inet_domainstrlen];//域名 char svr_dir[max_path_file_len]; //文件路径 char svr_ip[max_ip_str_len]; int port;}url_result_t; 功能:
解析url字符串,并将解析结果存放在result中 返回值;
成功返回 url_ok失败返回 url_error 2. void remove_quotation_mark() void remove_quotation_mark(char *input) 参数
input:字符串 功能
去掉字符串中的双引号 返回值
无 3. parse_domain_dir int parse_domain_dir(char *url,url_result_t *result) 参数
url:执行去掉协议头的url字符串,比如:peng:pass@baidu.com/dir/index.htmlresult :url解析后的结果存放在该结构体中 功能
解析出url中用户名、密码、域名/ip、文件路径等信息 返回值
成功:url_ok失败:url_error 4. check_is_ipv4() int check_is_ipv4(char *domain) 参数
domain:指向一个域名或者ip地址点分十进制字符串,最大长度为:max_url_len 功能
判断domain中存放的是不是合法的ip地址 返回值
1:是ip地址-1:不是ip地址 5、dns_resoulve() int dns_resoulve(char *svr_ip,const char *domain) 参数
svr_ip:存放dns协议解析过的域名对应的ip地址点分十进制字符串domain:域名字符串 功能
将domain中的域名,通过dns协议解析成对应的ip地址 返回值
成功:url_ok失败:url_error 五、运行 测试程序
void main(void){ int ret; char url_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---------------);} 执行结果
六、代码获取 完整代码可以进入仓库获取:
https://gitee.com/yikoulinux/url 原文标题:c语言实现url解析小实例
文章出处:【微信公众号:嵌入式arm】欢迎添加关注!文章转载请注明出处。
美光5200系列 SATA SSD:基于64层3D NAND技术,简便且经济高效
基于MFRC530射频芯片及单片机实现联机型门禁控制系统的设计
模拟电路网络课件 第十九节:金属-氧化物-半导体场效应管
3D7220D-10延时线
OPPOR11什么时候上市?OPPOR11最新消息: OPPOR11携手OPPOR11Plus2000万超清双摄,男神陈伟霆与你相约,不见不散
编写一个用于解析url的小例子
恩德斯豪斯全球口径最大的流量仪表标定设备落户苏州工业园区
快商通声纹助力解决老年人所面临的“数字鸿沟”问题
力矩电机接线图_力矩电机控制器接线图
英飞凌功率器件和单片机技术在能源利用和汽车电子的应用
电化学传感器多孔eptfe疏水膜材料的特点是什么
智能合约用的ERC标准是什么
未来自动泊车系统中建图定位的各类算法将进一步融合
全项目食品安全检测仪的检测项目
橡胶密度测试步骤和使用注意事项
为安装鸿蒙系统换手机?
一边破产合并,一边融资不断,海内外激光雷达公司的悲欢并不相通
SK Hynix的72L NAND快闪存储器与各家64L的对比分析详解
关于存储技术的发展趋势分析
场效应晶体管栅极电流是多大