我的编程空间,编程开发者的网络收藏夹
学习永远不晚

c语言怎么实现http下载器

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

c语言怎么实现http下载器

本篇内容主要讲解“c语言怎么实现http下载器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“c语言怎么实现http下载器”吧!

一、介绍

最近做ota升级需要用到http下载,所以写了一下http下载器
实现流程
1、解析url网址的域名和文件名
2、获取ip地址
3、构建http请求头发送到服务器
4、解析回复
5、下载文件

环境ubuntu linux
c语言
开源链接

main.c

#include <stdio.h>#include "http_download.h"int main(int argc, char const *argv[]){    if (argc == 1)    {        printf("Input a valid URL \n");        exit(0);    }    else    {        http_download_file(argv[1]);    }    return 0;}

http_download.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <arpa/inet.h>#include <netdb.h>#include <fcntl.h>#include "tcp.h"typedef struct {    int status_code;//HTTP/1.1 '200' OK    char content_type[128];//Content-Type: application/gzip    long content_length;//Content-Length: 11683079    char file_name[256];}resp_header_def;resp_header_def resp;//头信息#if 0下载分为以下几个过程1、解析出下载地址中的域名和文件名2、通过域名获取服务器的IP地址3、与目标服务器建立连接4、构建http请求头并将其发送到服务器5、等待服务器响应然后接收响应头6、解析响应头, 判断返回码, 分离开响应头, 并且响应的正文内容以字节形式写入文件, 正文内容与头部用两个\n\r分开#endif#define print_LOG(format, ...)     {\printf(format, ##__VA_ARGS__);}//解析网址//输入url,输出域名、端口、文件名static int Parsing_urls(char *url, char *domain, int *port, char *filename){    int i,j,start;    char *patterns[] = {"http://", "https://", NULL};    *port = 80;    //解析域名,就是http://或者https://到/的内容    for(i = 0; patterns[i]; i++)    {        if(strncmp(url, patterns[i], strlen(patterns[i])) == 0)        {            start = strlen(patterns[i]);        }    }    //复制域名    j = 0;    for ( i = start; url[i] != '/' && url[i] != '\0'; i++,j++)    {        domain[j] = url[i];    }    domain[i] = '\0';        //解析端口,冒号后面就是端口    char pos = strstr(domain, ":");    if(pos)    {        sscanf(pos, ":%d", port);    }    //如果有端口,需要删掉    for ( i = 0; i < (int)strlen(domain); i++)    {        if(domain[i] == ':')        {            domain[i] = '\0';            break;        }    }        //解析下载文件名,/后面就是文件名    j = 0;    for ( i = start; url[i] != '\0'; i++)    {        if(url[i] == '/')        {            j = i + 1;            memcpy(filename, &url[j], strlen(&url[j]));        }    }    i = strlen(&url[j]);    filename[i] = '\0';    return 0;}//通过域名获取ipstatic int Domain_to_ip(char *domain, char *ip){    int i;    struct hostent *host = gethostbyname(domain);    if(host == 0)    {        *ip = NULL;        return -1;    }    //找到不为空的地址    for ( i = 0; host->h_addr_list[i]; i++)    {        strcpy(ip, inet_ntoa( * (struct in_addr*) host->h_addr_list[i]));        break;    }    return 0;}//构建请求头信息static int Set_request_headers(char *header, char *url, char *domain){    int ret = 0;    sprintf(header, \            "GET %s HTTP/1.1\r\n"\            "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"\            "User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537(KHTML, like Gecko) Chrome/47.0.2526Safari/537.36\r\n"\            "Host:%s\r\n"\            "Connection:close\r\n"\            "\r\n"\        ,url, domain);    ret = strlen(header);    return ret;}static char *get_response(){    int len, lencnt  = 0,mem_size = 4096;    char *rcvbuff = (char *)malloc( mem_size*sizeof(char) );    char *response = (char *)malloc( mem_size*sizeof(char) );    while((len = tcp_client_rcv(rcvbuff, 1)) != 0)    {        //动态调整缓存大小        if((lencnt + len) > mem_size)//判断缓存是否超限        {            //重新分配内存            mem_size *= 2;            char *tmp = (char *)realloc(response, mem_size*sizeof(char));            if(tmp == NULL)            {                printf("realloc fail\n");                exit(-1);            }            response = tmp;        }        rcvbuff[len] = '\0';        strcat(response, rcvbuff);        //找到响应头的头部信息, 两个"\n\r"为分割点        int flag = 0;        int i = strlen(response) - 1;        for (; response[i] == '\n' || response[i] == '\r';            i--, flag++);        {            if (flag == 4)//最多找4次,没找到                break;        }        lencnt += len;    }    free(rcvbuff);    return response;}//获取回复头的信息static int get_resp_header(const char *response, resp_header_def *resp){    //查找HTTP/    char *pos = strstr(response, "HTTP/");    if (pos)        sscanf(pos, "%*s %d", &resp->status_code);//返回状态码    pos = strstr(response, "Content-Type:");//返回内容类型    if (pos)        sscanf(pos, "%*s %s", resp->content_type);    pos = strstr(response, "Content-Length:");//内容的长度(字节)    if (pos)        sscanf(pos, "%*s %ld", &resp->content_length);    return 0;}//打印进度int progress_bar(int x){    int i;    char tmp[100] = {0};    static int x_old = 0;    if(x == x_old)    {        return 0;    }    x_old = x;    i = x/2;    if(i > 50)        i = 50;    memset(tmp, '=', i);    printf("\r%d%[%s]", x, tmp);    fflush(stdout);//立刻输出    return 0;}static int download_writefile(){    int length = 0;    int mem_size = 4096;//mem_size might be enlarge, so reset it    int buf_len = mem_size;//read 4k each time    int len = 0;    int fd = open(resp.file_name, O_CREAT | O_WRONLY, S_IRWXG | S_IRWXO | S_IRWXU);    if (fd < 0)    {        print_LOG("Create file failed\n");        exit(0);    }    //申请4k缓存    char *buf = (char *)malloc(mem_size * sizeof(char));    //读取文件    while ((len = tcp_client_rcv(buf, buf_len)) != 0 && length < resp.content_length)    {        write(fd, buf, len);        length += len;        progress_bar((length*100/resp.content_length));    }    if (length == resp.content_length)    {        print_LOG("\nDownload successful ^_^\n\n");    }    else    {        print_LOG("Finished length:%d,resp.content_length:%d\n",        length, resp.content_length);    }    close(fd);    return 0;}//http下载文件函数int http_download_file(char *url){    //char url[2048] = "127.0.0.1";    char domain[64] = {0};    char ip_addr[16] = {0};    int port = 80;    char file_name[256] = {0};    char header[2048] = {0};    char *response = 0;    //解析域名    Parsing_urls(url, domain, &port, file_name);    //解析ip    Domain_to_ip(domain, ip_addr);    print_LOG("download:\n url:%s\n domain:%s\n ip:%s\n port:%d\n filename:%s\n",                url, domain, ip_addr, port, file_name);    //发送下载请求    Set_request_headers(header, url, domain);    if(tcp_client_init(ip_addr,  port) == -1)    {        print_LOG("connect server fail\n");        return -1;    }    tcp_client_send(header, strlen(header));    print_LOG("\nsend request\n");    //print_LOG("send request:%s\n", header);    //解析回复    response = get_response();    get_resp_header(response, &resp);    print_LOG("response:%s\n", response);    free(response);    strcpy(resp.file_name, file_name);    print_LOG("\nres:\n content_length:%d\n file_name:%s\n Content-Type:%s\n",     resp.content_length,     resp.file_name,     resp.content_type);    //下载文件    print_LOG("\ndownload %s start ...\n", resp.file_name);    download_writefile();    return 0;}

download.h

#ifndef __HTTP_DOWNLOAD_H#define __HTTP_DOWNLOAD_Hint http_download_file(char *url);#endif

tcp.c

//-------tcp相关头文件------#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h> //close()static int socket_fd = 0;//tcp_client_init()//1、创建socket//2、配置为客户端//3、配置要连接的服务器ip和端口以及协议类型//4、连接服务器//5、收发数据//6、关闭连接int tcp_client_init(char *ip, int port){int ret;//1 2socket_fd = socket(AF_INET, SOCK_STREAM, 0);if(socket_fd == -1){printf("create socket fail\n");return -1;}//3 struct sockaddr_in servaddr;servaddr.sin_family = AF_INET;//IPv4协议servaddr.sin_port = htons(port);//服务器端口号servaddr.sin_addr.s_addr = inet_addr(ip);//设置服务器//4ret = connect(socket_fd, &servaddr, sizeof(servaddr));if(ret == -1){printf("connect %s fail\n", ip);return -1;}}//tcp_client_send()int tcp_client_send(char *buff, int len){int ret = 0;ret = write(socket_fd, buff, len);return ret;}//tcp_client_rcv()int tcp_client_rcv(char *buff, int len){int ret;ret = read(socket_fd, buff, len);return ret;}//tcp_client_close()int tcp_client_close(){close(socket_fd);}#define CLENT_NUM 2struct sockaddr_in sSever_c_sd[CLENT_NUM];static int socket_s_fd = 0;static int socket_c_fd[CLENT_NUM] = {0};//tcp_server_init()#if 01、创建socket2、设置本地ip和端口以及协议类型3、绑定4、监听5、等待客户端连接6、收发数据7、关闭连接#endifint tcp_server_init(int port){int ret;//1 socket_s_fd = socket(AF_INET, SOCK_STREAM, 0);if(socket_s_fd == -1){printf("create socket fail\n");return -1;}else{printf("create socket ok\n");}//2 struct sockaddr_in local_addr,c_addr;local_addr.sin_family = AF_INET;//IPv4协议local_addr.sin_port = htons(port);//服务器端口号local_addr.sin_addr.s_addr = INADDR_ANY;//设置服务器ip//3ret = bind(socket_s_fd, &local_addr, sizeof(local_addr));if(ret == -1){printf("bind fail\n");close(socket_s_fd);return -1;}else{printf("bind ok\n");}//4ret = listen(socket_s_fd, 3);if(ret == -1){printf("listen fail\n");close(socket_s_fd);return -1;}else{printf("listen ok\n");}//5socklen_t addrlen = 0;while(1){printf("wait client conect\n");socket_c_fd[0] = accept(socket_s_fd, &c_addr, &addrlen);if(addrlen != 0)break;sleep(1);}printf("client conect\n");return 0;}//tcp_server_send()int tcp_server_send(char c, char *buff, int len){write(socket_c_fd[c], buff, len);}//tcp_server_rcv()int tcp_server_rcv(char c, char *buff, int len){int ret;ret = read(socket_c_fd[c], buff, len);return ret;}//tcp_server_close()int tcp_server_close(){close(socket_s_fd);}

tcp.h

#ifndef __TCP_H#define __TCP_Hint tcp_client_init(char *ip, int port);int tcp_client_send(unsigned char *buff, int len);int tcp_client_rcv(unsigned char *buff, int len);int tcp_client_close();int tcp_server_init( int port);int tcp_server_send(char c, unsigned char *buff, int len);int tcp_server_rcv(char c, unsigned char *buff, int len);int tcp_server_close();#endif

编译脚本

rm -rf main sscom32.zipgcc main.c http_download.c tcp.c -o main -w./main http://xzd.197946.com/sscom32.zip

测试效果
http://xzd.197946.com/sscom32.zip

c语言怎么实现http下载器
c语言怎么实现http下载器
c语言怎么实现http下载器

到此,相信大家对“c语言怎么实现http下载器”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

c语言怎么实现http下载器

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

c语言怎么实现http下载器

本篇内容主要讲解“c语言怎么实现http下载器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“c语言怎么实现http下载器”吧!一、介绍最近做ota升级需要用到http下载,所以写了一下http下
2023-06-20

基于C语言实现http下载器

做OTA升级功能时,我们能直接拿到的往往只是升级包的链接,需要我们自己去下载,这时候就需要用到http下载器。本文将利用C语言实现简单的http下载器,感兴趣的可以了解一下
2022-12-28

c语言怎么实现函数重载

在C语言中,没有直接支持函数重载的特性。函数重载是一个面向对象编程语言(如C++)提供的特性,它允许定义名称相同但参数列表不同的多个函数。在C语言中,可以通过以下方式模拟函数重载:1. 使用不同的函数名:为不同的功能使用不同的函数名,例如`
2023-10-25

c语言重载运算符怎么实现

C语言不支持重载运算符,只能通过函数来实现类似的功能。例如,可以通过定义一个函数来代替重载的加法运算符:#include typedef struct {int x;int y;} Point;Point add(Point p1, P
2023-10-25

C++中怎么通过C语言实现函数重载

这篇文章给大家介绍C++中怎么通过C语言实现函数重载,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C++函数重载的相关模拟代码:int (*func)(void); int func1(void) { int
2023-06-17

c语言多线程负载均衡怎么实现

在C语言中,可以使用线程库pthread来实现多线程负载均衡。1. 首先,创建一个主线程来分配任务给工作线程。可以使用队列或者其他数据结构保存任务。2. 创建一组工作线程,每个线程都会循环执行以下步骤:a. 线程从任务队列中获取一个任务。b
2023-09-01

c语言怎么实现类

c 语言中实现类的途径有四种:结构体和函数指针:使用结构体封装数据和函数指针访问方法。宏和预处理器:宏定义类方法名,预处理器生成实现代码。编译器扩展:某些编译器支持面向对象编程扩展,允许定义类和方法。第三方库:例如 gobject、gio、
c语言怎么实现类
2024-04-13

Go语言怎么实现HTTP服务器和客户端

在Go语言中,可以通过使用标准库中的"net/http"包来实现HTTP服务器和客户端。下面是一个简单的HTTP服务器示例:package mainimport ("fmt""net/http")func handler(w http
Go语言怎么实现HTTP服务器和客户端
2024-04-12

c语言排序怎么实现

c 语言中实现排序可以使用多种算法,包括:冒泡排序:比较相邻元素,将较小的元素向前移动。选择排序:找到无序序列中的最小元素,并与第一个元素交换位置。插入排序:将元素逐个插入到已有序序列中。归并排序:分治排序,合并排序后的左右两半。快速排序:
c语言排序怎么实现
2024-05-15

C语言怎么实现协程

这篇文章主要介绍“C语言怎么实现协程”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C语言怎么实现协程”文章能帮助大家解决问题。协程是一种用户空间的非抢占式线程,主要用来解决等待大量的IO操作的问题。
2023-06-17

C#中怎么实现多语言

这篇文章给大家介绍C#中怎么实现多语言,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C#实现多语言的方法是通过配置文件实现,通过从配置文件中读取资源,然后在显示窗口的时候,即Load()方法中,动态显示相应的选择语言。
2023-06-17

怎么用c语言实现类

在 c 语言中,类无法直接实现,但可以通过使用结构体、函数、指针和宏来模拟类行为。这种方式允许:使用结构体表示类的属性或字段。使用函数表示类的行为或方法。使用指针存储对结构体的引用,代表类的对象。使用宏定义类的符号,类似于面向对象语言中的类
怎么用c语言实现类
2024-04-13

C语言队列怎么实现

今天小编给大家分享一下C语言队列怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。队列的实现基本概念队列:只允许在一端进
2023-06-29

c语言怎么实现清屏

在C语言中,可以使用system函数来清屏。具体实现如下:```c#include int main() {system("clear"); // 清屏命令return 0;}```在Windows系统中,清屏命令为"cls",可以将上述
2023-08-18

怎么使用C语言实现计时器

本篇内容主要讲解“怎么使用C语言实现计时器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用C语言实现计时器”吧!实现思路简单介绍一下我的实现思路:本文包括三个版本,分别是极简版、普通版、高
2023-06-25

c语言定时器功能怎么实现

在C语言中,可以使用``头文件中的`sleep()`函数来实现简单的定时器功能。`sleep()`函数用于使程序暂停执行一段时间,参数是要暂停的秒数。可以通过循环调用`sleep()`函数来实现定时器的功能。例如,以下代码将每隔1秒输出一次
2023-08-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录