一、前言

前面一口君写了一篇关于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. MAC下Cowardly refusing to 'sudo brew install解决方案

    副标题:<论学习英语的重要性> 在执行'sudo brew install cmake'的时候报错,错误信息如下. (一脸懵逼) 解决方案: 其实报错信息都说好了,大概意思是不能用管理员权 ...

  2. Kubernetes 审计(Auditing)

    目录 一.系统环境 二.前言 三.Kubernetes 审计简介 四.审计策略简介 五.启用审计 5.1 引入审计 5.2 启用审计 六.审计策略 6.1 记录审计阶段为:ResponseStarte ...

  3. C++ 史上首次超越 C,Python 第二!

    TIOBE 公布了 2024 年 6 月的编程语言排行榜--C++ 史上首次超越 C,跃至榜二,仅次于 Python. C++ 是一种广泛应用于嵌入式系统.游戏开发和金融交易软件等领域的语言,在本月成 ...

  4. Taro 滚动切换tab页

    import React, { Component } from 'react' import { View, Text, ScrollView } from '@tarojs/components' ...

  5. ubuntu podman相关

    前言 记录podman的安装.配置以及一些常用操作,会不定时更新: 正文 1. podman 安装以及配置 ubuntu 安装 podman sudo apt update sudo apt inst ...

  6. C#进行图片压缩(对jpg压缩效果最好)

    直接上代码 1 public static class ImageCompress 2 { 3 /// <summary> 4 /// 图片压缩 5 /// </summary> ...

  7. SQL注入方法

    目录 前言 如何测试与利用注入点 手工 注入思路 工具 sqlmap -r -u -m --level --risk -v -p --threads -batch-smart --os-shell - ...

  8. yb课堂 vue里面的状态管理vuex 《四十》

    文档:https://vuex.vuejs.org/zh/ 在store/下index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use ...

  9. Go微服务开发指南

    在这篇深入探讨Go语言在微服务架构中的应用的文章中,我们介绍了选择Go构建微服务的优势.详细分析了主要的Go微服务框架,并探讨了服务发现与注册和API网关的实现及应用. 关注TechLead,复旦博士 ...

  10. BigDecimal的精度与刻度

    BigDecimal是Java中用于高精度算术运算的类.当您需要精确地处理非常大或非常小的数字时,例如在金融计算中,它特别有用.由于众所周知得原因,Double这种类型在某些情况下会出现丢失精度的问题 ...