Linux下实现C语言的http请求实现

2023-05-16

该文件为转载文章,作为学习和个人笔记使用
(原文地址:)
https://blog.csdn.net/songfeihu0810232/article/details/54892149

  1. 前言
    Linux下的http请求有许多种方式,其中curl库是C语言封装的一个强大的库,使用curl比封装socket更加方便。cJSON是一个小型的json封装库,可以把数据封装成json格式。本文介绍了这两种技术,并通过此技术完成了Linux下的http请求,同时把代码封装到quagga下,quagga运行时可以正常创建数据到ONOS。

  2. Linux下http请求实现
    2.1. curl简介
    curl命令是一个功能强大的网络工具,它能够通过http、ftp等方式下载文件,也能够上传文件。curl命令使用了libcurl库来实现,libcurl库常用在C程序中用来处理HTTP请求,curlpp是libcurl的一个C++封装,这几个东西可以用在抓取网页、网络监控等方面的开发,而curl命令可以帮助来解决开发过程中遇到的问题。本文档就是使用curl完成http请求。

2.1.1. 全局初始化
应用程序在使用libcurl之前,必须先初始化libcurl。libcurl只需初始化一次。可以使用以下语句进行初始化:

curl_global_init();

curl_global_init()接收一个参数,告诉libcurl如何初始化。参数CURL_GLOBAL_ALL 会使libcurl初始化所有的子模块和一些默认的选项,通常这是一个比较好的默认参数值。还有两个可选值:

CURL_GLOBAL_WIN32

只能应用于Windows平台。它告诉libcurl初始化winsock库。如果winsock库没有正确地初始化,应用程序就不能使用socket。在应用程序中,只要初始化一次即可。

CURL_GLOBAL_SSL

如果libcurl在编译时被设定支持SSL,那么该参数用于初始化相应的SSL库。同样,在应用程序中,只要初始化一次即可。

libcurl有默认的保护机制,如果在调用curl_easy_perform时它检测到还没有通过curl_global_init进行初始 化,libcurl会根据当前的运行时环境,自动调用全局初始化函数。但必须清楚的是,让系统自已初始化不是一个好的选择。

当应用程序不再使用libcurl的时候,应该调用curl_global_cleanup来释放相关的资源。在程序中,应当避免多次调用curl_global_init和curl_global_cleanup。它们只能被调用一次。

2.1.2. easy interface
libcurl中被称为easy interface的api函数,所有这些函数都是有相同的前缀:curl_easy 。

要使用easyinterface,首先必须创建一个easy handle,easy handle用于执行每次操作。基本上,每个线程都应该有自己的easy handle用于数据通信(如果需要的话)。千万不要在多线程之间共享同一个easy handle。下面的函数用于获取一个easy handle:

CURL *easy_handle =curl_easy_init();

在easyhandle上可以设置属性和操作(action)。easy handle就像一个逻辑连接,用于接下来要进行的数据传输。

使用curl_easy_setopt函数可以设置easy handle的属性和操作,这些属性和操作控制libcurl如何与远程主机进行数据通信。一旦在easy handle中设置了相应的属性和操作,它们将一直作用该easyhandle。也就是说,重复使用easy hanle向远程主机发出请求,先前设置的属性仍然生效。

easy handle的许多属性使用字符串(以\0结尾的字节数组)来设置。通过curl_easy_setopt函数设置字符串属性时,libcurl内部会自动拷贝这些字符串,所以在设置完相关属性之后,字符串可以直接被释放掉(如果需要的话)。

后面章节会根据http的get和post接口对常用的easy handle函数进行说明。

2.2. cJSON简介
cJSON是在C语言中解析JSON的开源库,在cJSON中,一个key-value键值对被解析并存放在一个cJSON结构体变量中,其value取值集为:FALSE,TRUE,NULL,NUMBER,STRING,OBJECT,ARRAY。cJOSN库,仅有两个文件cJSON.c和cJSON.h。

2.2.1. cJSON使用说明
下面使用cJSON组装以下json数据

{
“mac”: “46:E4:3C:A4:11:12”,

"vlan": "-1",

"ipAddresses":  ["222.222.233.2"],

"location": {
    "elementId":    "of:0000001e08000fe3",

    "port": "31"

}

}

代码如下:

//创建一个object

cJSON *root =cJSON_CreateObject();

cJSON_AddItemToObject(root,"mac",cJSON_CreateString("46:E4:3C:A4:13:12"));

cJSON_AddStringToObject(root,"vlan","-1");

cJSON*array = NULL;

cJSON_AddItemToObject(root,"ipAddresses",array=cJSON_CreateArray());

cJSON_AddItemToArray(array,cJSON_CreateString("192.168.10.2"));

//创建一个子object,将此object添加到root中

cJSON*location = NULL;

cJSON_AddItemToObject(root,"location",location=cJSON_CreateObject());

cJSON_AddStringToObject(location,"elementId","of:0000001e08000fe3");

cJSON_AddStringToObject(location,"port","31");

//将json结构格式化到缓冲区

char*buf = cJSON_Print(root);

//执行http请求函数

http_client_thttp_read_client;

http_client_read_init(&http_read_client,temp, buf);

//数据使用完之后,把内存释放掉

cJSON_Delete(json);

free(buf);

2.3. http的post请求
int http_client_read_init(http_client_t*http_client, const char *url, char *szJsonData)

{
if (!url) {
return -1;

}

//初始化libcurl,设置默认参数

CURLcode return_code = curl_global_init(CURL_GLOBAL_ALL);

if (CURLE_OK != return_code) {
printf(“initlibcurl failed.\n”);

   return -1;

}

//获取easy handle

http_client->handle = curl_easy_init();

if (!http_client->handle) {
return -1;

}

//通过CURLOPT_URL属性设置url

curl_easy_setopt(http_client->handle, CURLOPT_URL, url);

//通过CURLOPT_HTTPHEADER定义http消息的header

struct curl_slist *plist = NULL;

plist = curl_slist_append(plist,  

             "Content-Type:application/json"); 

curl_easy_setopt(http_client->handle, CURLOPT_HTTPHEADER, plist);

printf("Thejson is: %s\n", szJsonData);

//通过CURLOPT_POSTFIELDS设置要POST的数据

curl_easy_setopt(http_client->handle,CURLOPT_POSTFIELDS, szJsonData);

//通过CURLOPT_USERPWD属性来设置用户名与密码。参数是”user:password “的字符串

curl_easy_setopt(http_client->handle,CURLOPT_USERPWD, "karaf:karaf");

//使用curl_easy_perform执行上传数据

curl_easy_perform(http_client->handle);

//任务执行结束使用curl_easy_cleanup把内存释放

curl_easy_cleanup(http_client->handle);

return 0;

}

2.4. http的get请求
int http_client_init(http_client_t*http_client, const char *url, write_cb_t *write_data, void *userp)

{
if (!url) {
return -1;

}

//初始化libcurl,设置默认参数

CURLcode return_code;

return_code= curl_global_init(CURL_GLOBAL_ALL);

if (CURLE_OK != return_code) {
printf(“initlibcurl failed.\n”);

   return -1;

}

//获取easy handle

http_client->handle = curl_easy_init();

if (!http_client->handle) {
return -1;

}

//通过CURLOPT_URL属性设置url

curl_easy_setopt(http_client->handle,CURLOPT_URL, url);

//注册回调函数write_cb,回调函数将会在接收到数据的时候被调用

curl_easy_setopt(http_client->handle, CURLOPT_WRITEFUNCTION, write_data); //通过CURLOPT_USERPWD属性来设置用户名与密码。参数是”user:password “的字符串

curl_easy_setopt(http_client->handle,CURLOPT_USERPWD, "karaf:karaf");

if (userp) {
//设置写数据的变量

   curl_easy_setopt(http_client->handle, CURLOPT_WRITEDATA, userp);

}

//使用curl_easy_perform执行上传数据

curl_easy_perform(http_client->handle);

//任务执行结束使用curl_easy_cleanup把内存释放

curl_easy_cleanup(http_client->handle);

return 0;

}

//回调函数,将接收到的数据保存到本地文件中,同时显示在控制台上。

static size_t write_data(void *buf, size_tsize, size_t nmemb, void *userp)

{
FILE *fp = (FILE *)userp;

size_t return_size = fwrite(buf, size, nmemb, fp);

printf(“write_data: %ld, return_size: %ld\n”, nmemb,return_size);

return return_size;

}

2.5. http的del请求
//获取easy handle

http_client->handle = http_client_init();

if (!http_client->handle) {
return -1;

}

// 通过CURLOPT_URL属性设置url

curl_easy_setopt(http_client->handle, CURLOPT_URL, url);

// 设置http发送的内容类型为JSON 

struct curl_slist *plist = NULL;

//plist = curl_slist_append(plist,

    //"Content-Type:application/json");

curl_easy_setopt(http_client->handle,CURLOPT_HTTPHEADER, plist);

// 设置要POST的JSON数据 

//curl_easy_setopt(http_client->handle, CURLOPT_POSTFIELDS,szJsonData);

curl_easy_setopt(http_client->handle,CURLOPT_CUSTOMREQUEST, "DELETE");

curl_easy_setopt(http_client->handle,CURLOPT_USERPWD, "karaf:karaf");

2.6. 编译并执行
代码完成之后,使用gcc运行时需要带如下参数:

gcc -o http_client http_client.ccJSON.c -lcurl –lm

编译之后开始运行

./http_client

通过抓包可以看到http报文

注意事项:

  1. -lcurl是链接curl库,如果运行报如下错误:

mlogc.c:32:23: error: curl/curl.h: No such fileor directory

mlogc.c:1091: error: expected ‘)’ before ‘*’token

mlogc.c: In function ‘logc_init’:

则需要安装如下依赖包:libcurl-dev, libcurl-devel

centOS上安装依赖包:

yum install libcurl-dev libcurl-devel

  1. –lm是链接math的库,由于cJSON需要调用math库,如果不添加会报如下错误:

  2. 如果有多个方法例如:get/post/delete等用到的URL一样,需要把如下代码,包含URL的头部注释掉,否则报文发布出去。

// 设置http发送的内容类型为JSON 

struct curl_slist *plist = NULL;

//plist = curl_slist_append(plist,

    //"Content-Type:application/json");

curl_easy_setopt(http_client->handle,CURLOPT_HTTPHEADER, plist);

————————————————
关注微信公众号 一起学习 ( 技术Code城 )

版权声明:本文为CSDN博主「安全防护技术」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/songfeihu0810232/article/details/54892149

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux下实现C语言的http请求实现 的相关文章

  • 尽管 if 语句,Visual Studio 仍尝试包含 Linux 标头

    我正在尝试创建一个强大的头文件 无需更改即可在 Windows 和 Linux 上进行编译 为此 我的包含内容中有一个 if 语句 如下所示 if defined WINDOWS include
  • .net-core:ILDASM / ILASM 的等效项

    net core 是否有相当于 ILDASM ILASM 的功能 具体来说 我正在寻找在 Linux 上运行的东西 因此为什么是 net core ildasm 和 ilasm 工具都是使用此存储库中的 CoreCLR 构建的 https
  • 内核的panic()函数是否完全冻结所有其他进程?

    我想确认内核的panic 功能和其他类似kernel halt and machine halt 一旦触发 保证机器完全冻结 那么 所有的内核和用户进程都被冻结了吗 是panic 可以被调度程序中断吗 中断处理程序仍然可以执行吗 用例 如果
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • Mac OS X 上的 /proc/self/cmdline / GetCommandLine 等效项是什么?

    如何在不使用 argc argv 的情况下访问 Mac OS X 上的命令行 在 Linux 上 我会简单地阅读 proc self cmdline or use GetCommandLine在 Windows 上 但我找不到 Mac OS
  • C修改printf()输出到文件

    有没有办法修改printf为了将字符串输出到文件而不是控制台 我尝试在互联网上查找一些内容 发现了类似的电话dup dup2 and fflush这可能与此有关 EDIT 也许我不清楚 问题是这是C考试问题 问题如下 解释一个通常将字符串输
  • 如何在 PHP 中使用 file_get_contents 获取图像的 MIME 类型

    我需要获取图像的 MIME 类型 但我只有图像的正文file get contents 是否有可能获取 MIME 类型 是的 你可以这样得到它 file info new finfo FILEINFO MIME TYPE mime type
  • 如何查找哪个 Yocto 项目配方填充图像根文件系统上的特定文件

    我经常与 Yocto 项目合作 一个常见的挑战是确定文件为何 或来自什么配方 包含在 rootfs 中 这有望从构建系统的环境 日志和元数据中得出 理想情况下 一组命令将允许将文件链接回源 即配方 我通常的策略是对元数据执行搜索 例如gre
  • Linux/POSIX:为什么 fork() 不分叉*所有*线程

    众所周知 POSIX下创建新进程的默认方式是使用fork 在 Linux 下 这在内部映射到clone 我想知道的是 众所周知 当一个人打电话时fork 子进程是用单个线程创建的 调用的线程fork cf https linux die n
  • cdc_acm:无法设置 dtr/rts - 无法与 USB cdc 设备通信

    我试图使用 pic24fj128gb206 枚举 usb cdc 设备 设备似乎已正确枚举 但是当我将设备连接到 Linux PC 时 我从内核收到以下警告消息 cdc acm 1 8 1 6 7 1 0 failed to set dtr
  • 如何让 Node.js 作为后台进程运行并且永不死掉?

    我通过 putty SSH 连接到 linux 服务器 我尝试将其作为后台进程运行 如下所示 node server js 然而 2 5 小时后 终端变得不活动 进程终止 即使终端断开连接 我是否也可以使进程保持活动状态 Edit 1 事实
  • express.js api 应用程序中的内存泄漏

    我正在运行一个express js应用程序 它用作REST API 一个端点启动 puppeteer 并使用多个过程测试我的网站 启动应用程序并持续消耗端点后 我的 docker 容器每小时都会耗尽内存 如下所示 首先 我认为我的 pupp
  • 在 HTML 表单中使用 PUT 方法

    我可以在 HTML 表单中使用 PUT 方法将数据从表单发送到服务器吗 根据HTML标准 https www w3 org TR html5 sec forms html element attrdef form method 你可以not
  • 为什么 XRecordDisableContext() 不起作用?

    void Callback XPointer XRecordInterceptData pRecord std cout lt lt my logs n int main if auto const pDisplay XOpenDispla
  • [A-Z] 表示 [A-Za-z] 是怎么回事?

    我已经注意到 至少在我使用的一些基于 Unix 的系统上 ls A Z 已经给了我预期的结果ls A Za z 让我无法轻松获得以大写字母开头的该死的文件列表 我刚刚遇到了同样的事情grep 我无法让它停止与小写字母匹配 A Z 直到我最终
  • 如何在文件中搜索多行模式?

    我需要找到包含特定字符串模式的所有文件 我想到的第一个解决方案是使用find管道与xargs grep find iname py xargs grep e YOUR PATTERN 但是 如果我需要查找跨越多行的模式 我就会陷入困境 因为
  • 使用awk将列中的值替换为txt文件中的另一个值

    我是 Linux 和 awk 脚本编写的新手 我有 tab delim txt 文件 如下所示 AAA 134 145 Sat 150 167 AAA 156 167 Sat 150 167 AAA 175 187 Sat 150 167
  • 如何在Linux中自动启动需要X的应用程序

    我试图在系统进入运行级别 5 时自动启动 X 应用程序 这样做的正确方法是什么 我写了一个脚本并将其放在 etc init d 中 我已运行适当的 chkconfig 命令来设置 etc rcX d 目录中的符号链接 一切工作正常 除了当我
  • 如何找到进程启动时使用的原始用户名?

    有一个 perl 脚本需要以 root 身份运行 但我们必须确保运行该脚本的用户最初没有以用户 foo 身份登录 因为它将在脚本运行期间被删除 那么 我如何查明自登录以来可能已多次起诉的用户是否在该链中的任何时间都没有模拟过 foo 我发现

随机推荐

  • 毕业设计--球上自平衡机器人

    目录 前言 一 机器人原理分析 二 控制器设计 三 程序部分 四 硬件清单 五 电路设计 六 结构设计 七 总结与展望 总结 展望 2021 8 18更新 xff1a 看到评论区很多人对这个机器人比较感兴趣 xff0c 把之前挖好的坑填一下
  • ROS入门之CmakeList.txt详讲

    本文为进来学习的总结 xff0c 记录了学习CmakeList txt文档的各个步骤 xff0c 适合从零开始理解CmakeList txt xff0c 可能存在错误之处 xff0c 望批评指正 0 Cmake的起源 为什么有CmakeLi
  • 2 如何给Gazebo中的仿真机械臂添加一个力传感器?

    1 你得有一个仿真机械臂 简单地说你首先的拥有一个能够在Gazebo当中使用的机械臂的URDF文件 xff0c 必须要包含visual collision和inertial三大标签 出于个人习惯 xff0c 这里直接使用UR官方提供的UR5
  • C#学习之事件的本质

    在注册事件时 xff0c 使用EventHandler委托 xff1b 摘要 表示将用于处理不具有事件数据的事件的方法 参数 sender 事件源 e 不包含事件数据的对象 public delegate void EventHandler
  • ..\OBJ\USART.axf: Error: L6218E: Undefined symbol I2C_CheckEvent (referred from oled_i2c.o).

    OBJ USART axf Error L6218E Undefined symbol I2C CheckEvent referred from oled i2c o OBJ USART axf Error L6218E Undefined
  • React 应用中的异步数据请求----fetch,以及fetch的优缺点

    React 应用中的异步数据请求 fetch 与Vue js一样 xff0c React官方也没有提供服务器端接口异步请求方案 xff1b 可以使用第三方的axios模块 xff0c 或者H5新增的原生技术 xff1a fetch 抓取 有
  • hmdb51数据集,视频+标签

    目录 视频下载链接 标签下载 hmdb介绍 其它 用于行为识别还需 帧标注 xff08 rawframe annotation xff09 视频标注 xff08 video annotation xff09 目录 视频下载链接 标签下载 h
  • vscode 连接服务器(Ubuntu系统),安装anaconda上运行深度学习代码

    目录 VSCODE的官网 Visual Studio Code Code Editing Redefined 1 安装 Romote SSH 2 添加服务器 3 进入服务器 4进入服务器文件 5 在Ubuntu上安装anconda xff0
  • nohub 和 & 在linux上不间断后台运行程序

    1 nohub xff08 没安装的要先安装 xff09 用途 xff1a 不挂断地运行命令 语法 xff1a nohup Command Arg amp 无论是否将 nohup 命令的输出重定向到终端 xff0c 输出都将附加到当前目录的
  • 《30天自制操作系统》:值得推荐的一本好书

    自己编写一个操作系统 xff0c 是许多程序员的梦想 也许有人曾经挑战过 xff0c 但因为太难而放弃了 其实你错了 xff0c 你的失败并不是因为编写操作系统太难 xff0c 而是因为没有人告诉你那其实是一件很简单的事 那么 xff0c
  • NTU RGB+D 120 划分训练集和测试集,生成标签文件。

    NTU RGB 43 D 120 总共有120类和114 480个样本 大小约为262G 包括 RGB视频分辨率为1920x1080 xff0c 深度图和IR xff08 红外 xff09 视频的分辨率均为512x424 xff0c 3D骨
  • 7z.001压缩包解压方法。(Window+Linux)

    之前遇到过的问题 xff1a Open ERROR Can not open the file as 7z archive 解决 xff1a 1 分卷文件需合并成一个7z压缩文件 1 1 如下所示是一个7z 结尾的文件 xff0c 对它的解
  • Linux 服务器上传下载文件到阿里网盘

    1 查看Linux系统架构 dpkg print architecture 2 下载安装 xff08 根据系统版本安装 xff09 2 1下载地址 https github com tickstep aliyunpan releases 2
  • CondaEnvException: Pip failed 或 Could not find a version that satisfies the requirement 问题

    1 错误实例 xff08 Could not find a version that satisfies the requirement imageio 61 61 2 27 0 xff09 2 解决方法 2 1 若对imageio的版本要
  • Linux中系统盘空间不足和显存没有释放问题

    1 系统盘空间不足 以下两个是可以直接删除 xff0c 不影响系统运行的目录 xff0c 所以首先直接删除 du sh root miniconda3 pkgs amp amp rm rf root miniconda3 pkgs cond
  • Ubuntu KCF 代码运行

    最近刚接触kcf xff0c 在Ubuntu上运行代码 xff0c 碰到一些问题 xff0c 借鉴了网上其他人的方法 xff0c 简单记录一下过程 KCF代码下载 KCF的代码可以去作者的网站去下载 xff1a http www robot
  • PADS学习笔记之绪论

    学习目的 在学校里的时候使用一直都是AD xff0c 现在即将毕业了 xff0c 来公司实习之后发现基本不用AD xff08 可能是怕收到律师函 xff09 xff0c 公司主要用的是PADS xff0c 某些项目也会用到cadence 虽
  • 软件工程中的框架

    什么是框架 框架 Framework 是构成一类特定软件可复用设计的一组相互协作的类 框架规定了你的应用的体系结构 它定义了整体结构 xff0c 类和对象的分割 xff0c 各部分的主要责任 xff0c 类和对象怎么协作 xff0c 以及控
  • Python argparse模块详解

    argparse是python用于解析命令行参数和选项的标准模块 xff0c 用于代替已经过时的optparse模块 官方文档中讲到的 xff0c 本文基本都提到了 xff0c 但只是简要记录 xff0c 如果需要深入理解 xff0c 可查
  • Linux下实现C语言的http请求实现

    该文件为转载文章 xff0c 作为学习和个人笔记使用 xff08 原文地址 xff09 https blog csdn net songfeihu0810232 article details 54892149 前言 Linux下的http