编写一个简单的用于解析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 tinet/in.h> #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.1"addrptr:转换结果存放在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,若出错则为-1const 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},};
四、程序流程图。威廉希尔官方网站
培训咨询18925402680
程序流程相对来说,比较简单,主函数功能说明如下: 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_dirint 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
|