一、前言

前面一口君写了一篇关于url的文章:

一文带你理解URI 和 URL 有什么区别?

本篇在此基础上,编写一个简单的用于解析url的小例子,

最终目标是解析出URL中所有的数据信息。

二、库函数

用到的几个库函数如下:

1. strncasecmp

头文件

#include<string.h>

函数定义

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<string.h>

函数定义

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 <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

函数声明

#include <arpe/inet.h>
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"转换为:0xC0A80101

addrptr类型为: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 <netdb.h>
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 443
struct 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.html
result :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.html
result :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("\n-------------result---------------\n"); printf("user:%s\n",url_result_t.user);
printf("pass:%s\n",url_result_t.pass);
printf("port:%d\n",url_result_t.port);
printf("domain:%s\n",url_result_t.domain);
printf("svr_dir:%s\n",url_result_t.svr_dir);
printf("svr_ip:%s\n",url_result_t.svr_ip); printf("-------------end---------------\n");
}

执行结果

六、代码获取

完整代码可以进入我的仓库获取

https://gitee.com/yikoulinux/url

或者公众号后台回复关键字:url

C语言实现url解析小实例的更多相关文章

  1. (转)使用 CJSON 在C语言中进行 JSON 的创建和解析的实例讲解

    使用 CJSON 在C语言中进行 JSON 的创建和解析的实例讲解   本文用代码简单介绍cjson的使用方法,1)创建json,从json中获取数据.2)创建json数组和解析json数组 1. 创 ...

  2. Objective-C之@类别小实例

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  3. Python(五)编程小实例

    Python(五)编程小实例 抓取网页信息,并生成txt文件内容! Python抓取网页技能--Python抓取网页就是我们常看见的网络爬虫,我们今天所要用到的就是我们Python中自带的模块,用这些 ...

  4. python+pcap+dpkt 抓包小实例

    #!/usr/bin/env python # -*- coding: utf-8 -*- """ 网络数据包捕获与分析程序 """ imp ...

  5. Python_爬虫小实例

    爬虫小实例 一.问题描述与分析 Q:查询某一只股票,在百度搜索页面的结果的个数以及搜索结果的变化. 分析: 搜索结果个数如下图: 搜索结果的变化:通过观察可以看到,每个一段时间搜索结果的个数是有所变化 ...

  6. Django 小实例S1 简易学生选课管理系统 4 实现登录页面

    Django 小实例S1 简易学生选课管理系统 第4节--实现登录页面 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 本文涉及到的新的额外知识点: ...

  7. Objective-C之代理设计模式小实例

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  8. OC小实例关于init方法不小心的错误

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  9. C语言文件操作解析(五)之EOF解析(转载)

      C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符.但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特 ...

  10. ssh框架的小实例(用户登录)

    刚学SSH框架写一个小实例,以便以后查看: 本案例简单的实现一个用户登录: 数据库方面就不写了,自己领悟吧!哈哈(根据user.hbm.xml文件就知道了) 我们一般可以创建下面几个包,什么意思呢,自 ...

随机推荐

  1. USB OTG有关协议

    想了解USB OTG的工作原理,需要知道三个协议: ADP:Attach Detection Protocol HNP:Host Negotiation Protocol SRP:Session Re ...

  2. VS Code Go开发环境配置

    1.安装Go 下载网址:https://go.dev/doc/install 根据自己的操作系统来进行安装,官网针对Windows.Linux.macOS都有对应教程.安装完成后打开终端,输入go v ...

  3. QT自定义右键菜单

    利用QMenu和QAction可以实现非常实用的右键菜单功能.具体实现思路如下: 1.在xxx.h文件中添加如下头文件 #include <QMenu> #include <QCon ...

  4. MySql常用日期时间查询

    -- 某一天所在周的第一天: -- 我们知道国外的星期的第一天是从星期天开始的,所以DAYOFWEEK('2017-3-10')函数的第一天是星期天: SELECT CASE WHEN DAYNAME ...

  5. 树莓派4B-GPIO控制步进电机

    树莓派4B-GPIO控制步进电机 硬件需求: 步进电机 树莓派 杜邦线 L298N驱动模块 选择步进电机 首先需要确认步进电机,因为步进电机可分为单极性和双极步进电动机两种,这两种电机的驱动方式是不同 ...

  6. eclipse注释取消注释

    方法一:使用Ctrl+/快捷键   1 第1步:在Eclipse中拖动鼠标,选中需要注释的代码,通常为连续多行代码. 2 第2步:按住Ctrl+/快捷键,如图所示. 3 第3步:会发现所选代码被&qu ...

  7. truncate table 与delete的区别

    1.DELETE ・DML语言 ・可以回退 ・可以有条件的删除 DELETE FROM 表名 WHERE 条件2.TRUNCATE TABLE ・DDL语言 ・无法回退 ・默认所有的表内容都删除 ・删 ...

  8. [oeasy]python0135_变量名与下划线_dunder_声明与赋值

    变量定义 回忆上次内容 变量 就是 能变的量 上次研究了 变量标识符的 规则 第一个字符 应该是 字母或下划线 合法的标识符可以包括 大小写字母 数字 下划线     还研究了字符串(str)的函数 ...

  9. PHP 程序员为什么依然是外包公司的香饽饽?

    大家好,我是码农先森. PHP 唯一的爽点就是开发起来「哇真快」这刚好和外包公司的需求相契合,在 Web 领域的芒荒年代 PHP 以王者姿态傲视群雄.如果 PHP 敢说第二,就没有哪门子语言敢称第一, ...

  10. Android SDK Build-tools的版本已经高于Android SDK Platform-tools版本 的解决办法

    解决Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!最近渐渐迁移到Android  ...