libevent服务GET/POST的简单使用

目录

  • 1、前言
  • 2、测试demo
    • 2.1、目录结构
    • 2.2、 测试源码
      • 2.2.1、http_server.cpp
      • 2.2.2、 http_server.h
    • 2.3、 编译
    • 2.4、 运行结果
      • 2.4.1、测试POST
      • 2.4.2 、测试GET请求

1、前言


项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信,比较常用的使用POSTGET方式带出MESSAGE。实际使用中为了减少工作量和代码复用,经常使用到三方库,比较常用的服务有libevent或boost中的网络库、muduo, 也可自行写一套socket系统调用的二次封装, 当然这种方式不利于快速开发, 学习还是可以的。

这篇文章主要使用libevent库,因为是c写的, 所以掌握libevent非常重要。

  • POST请求比较常用, 特别是针对一些数据比较小的场景,比如控制相关, 业务相关的。当然传图片也可以,传输效果过低不推荐。
  • 针对传输二进制比较大的数据, 可以使用GET方式。

针对以上,这里简单使用http的POST和GET方法解决以上问题。
关联:libevent库,链接libevent 源码地址
jsoncpp的编译和使用参考我的这篇文章: 链接C++库libjsoncpp使用

2、测试demo

测试demo写的比较唐突,所以可能存在一些内存释放等BUG,因此如果向使用一下demo的程序开发,需要renew代码和多调试。


2.1、目录结构

event目录|-- libevent头文件
http_server.cpp|-- CHttpServer 功能类,里面带main的测试程序 
http_server.h|-- CHttpServer 接口
libevent.a|-- libevent库
libevent_core.a|-- libevent库
libevent_pthreads.a|-- libevent库其中event目录是libevent编译后的头文件, *.a是libevent编译后的库静态文件,如果要链接动态库,请自行编译。

2.2、 测试源码

2.2.1、http_server.cpp

#include <unistd.h>#include <iostream>
#include <string>
#include <memory>			//shared_ptr,unique_ptr .etc#include "http_server.h"CHttpServer::CHttpServer():base_(nullptr), http_(nullptr), serverloopThread_(nullptr),isExit_(true), sock_(nullptr)
{if(!serverloopThread_){serverloopThread_ = new std::thread(&CHttpServer::serverDispatch, this);if(!serverloopThread_){std::cout << "创建线程失败!" << std::endl;}}
}CHttpServer::~CHttpServer()
{if(serverloopThread_){serverloopThread_->join();delete serverloopThread_; serverloopThread_ = nullptr;}
}int CHttpServer::pic_video_test(struct evhttp_request *_req, const std::string &strPath, const char *strParms/*参数query*/)
{/*1. 拿到文件数据*/FILE *fp = fopen("/tmp/test.pic", "rb");if(!fp){return -1;	}fseek(fp, 0, SEEK_END);size_t stream_size = ftell(fp);fseek(fp, 0, 0);printf("size:%d\n", stream_size);char *pStream = (char*)calloc(1, stream_size);if(!pStream){return -2;}fread(pStream, 1, stream_size, fp);fclose(fp); fp = (FILE*)0;/*添加一些headers*/evhttp_add_header(_req->output_headers, "Server", "帘下有白绿的服务");evhttp_add_header(_req->output_headers, "Connection", "close");struct evbuffer *buf = evbuffer_new();if(!buf){evhttp_send_error(_req, HTTP_INTERNAL, "Internal Error");return -255;}if(pStream && stream_size > 0){evhttp_add_header(_req->output_headers, "Content-Type", "img/jpg");int ret = evbuffer_add(buf, pStream, stream_size);printf("ret:%d\n", ret);free(pStream); pStream = 0;}else {#if 0		//增加异常信息响应evhttp_add_header(_req->output_headers, "Content-Type", "application/json;charset=UTF-8");Json::Value root;try {root["code"] = 300;root["msg"] = "打开文件异常,可能文件不存在或系统错误";}catch(std::exception &e){return -3;}Json::Value def;Json::StreamWriterBuilder::setDefaults(&def);def["emitUTF8"] = true;def["precisionType"] = "decimal";def["precision"] = 6;def["indentation"] = ""; // 压缩格式,没有换行和不必要的空白字符std::ostringstream stream;Json::StreamWriterBuilder stream_builder;stream_builder.settings_ = def;//Config emitUTF8std::unique_ptr<Json::StreamWriter> writer(stream_builder.newStreamWriter());writer->write(root, &stream);std::string strJson = stream.str();evbuffer_add(buf, strJson.c_str(), strJson.length());
#endif}evhttp_send_reply(_req, HTTP_OK, "done",buf);evbuffer_free(buf);printf("request,response Done.\n");return 0;
}//TODO : GET相关的开发工作int CHttpServer::method_GET_io_process(struct evhttp_request *req)
{if( !req ){return -1;}const char *uri = evhttp_request_get_uri(req);	//获取URI信息struct evhttp_uri *decoded = nullptr;const char *path;char *decoded_path;decoded = evhttp_uri_parse(uri);			//解析URI请求信息if(!decoded){evhttp_send_error(req, HTTP_BADREQUEST, 0);return -2;}path = evhttp_uri_get_path(decoded);	//获取http get请求路径if(!path) path="/";printf("path:%s\n", path);/*We need to decode it, to see what path the user really wanted.*/decoded_path = evhttp_uridecode(path, 0, NULL); 	//查询路径相关{char *}, get的请求APIif(!decoded_path){return -3;evhttp_send_error(req, HTTP_NOTFOUND, NULL);			//响应http错误信息}printf("decoded_path:%s\n", decoded_path);//获取uri中的参数部分const char * query = evhttp_uri_get_query(decoded); //query 参数, {char *}printf("query:%s\n", query);pic_video_test(req, decoded_path, query);if(decoded)evhttp_uri_free(decoded);if(decoded_path){free(decoded_path);decoded_path = 0;}}//TODO: POST私有协议相关的开发工作, 业务层
int CHttpServer::method_POST_io_process( struct evhttp_request *req )
{
//	Json::Value root;struct evbuffer *pEvbuffer(nullptr);pEvbuffer = evhttp_request_get_input_buffer(req);if(nullptr == pEvbuffer){//需要增加异常的响应, 这里暂忽略return -1;}int nJsonbodySize = 1024 * 10;char *pJsonbody = (char*)calloc(nJsonbodySize, sizeof(char));if(!pJsonbody){return -2;}int nread = 0;while(evbuffer_get_length(pEvbuffer)){nread += evbuffer_remove(pEvbuffer, pJsonbody, nJsonbodySize-1);}try {//解包{反序列化}//Json::Reader reader;//reader.parse(pJsonbody, root);}catch(std::exception &e){}/*请求数据的输出*///	1. 反序列化的逻辑处理,涉及到jsoncpp的库操作// 2. 根据项目业务做数据的转发处理{event}以及配置文件的读写操作// 3. 封Json包响应请求  //4. 发送struct evbuffer *pRespbuffer = evbuffer_new();if(!pRespbuffer){evhttp_send_error(req, HTTP_INTERNAL, "internal error");return -1;}evhttp_add_header(req->output_headers, "Connection", "close");evhttp_add_header(req->output_headers, "Content-Type", "application/json;charset=UTF-8");		//和客户端约定的编码方式,这里用的UTF-8std::string strRespJsonBody("这里是协议内相关Json");evbuffer_add_printf(pRespbuffer, "%s", strRespJsonBody.c_str());	//向evbuffer中增加messageevhttp_send_reply(req, 200, "ok", pRespbuffer);					//向socker发送操作evbuffer_free(pRespbuffer);										//释放操作if(pJsonbody){free(pJsonbody); pJsonbody = (char*)0;}return 0;
}void CHttpServer::serverIoExec(struct evhttp_request *req, void *arg)
{CHttpServer *_this = (CHttpServer*)arg;if(!req){return ;}	evhttp_cmd_type eMethod = evhttp_request_get_command(req);switch(eMethod){case EVHTTP_REQ_GET:{_this->method_GET_io_process(req);}break;case EVHTTP_REQ_POST:{_this->method_POST_io_process(req);}break;default:std::cout << "未知http方法" << std::endl;}return;
}void CHttpServer::serverDispatch()
{pthread_setname_np(pthread_self(), "ServerLoop");evthread_use_pthreads();base_ = event_base_new();if(nullptr == base_){std::cout << "create event_base failure!" << std::endl;goto FREE_BASE;}if(!(http_ = evhttp_new(base_))){std::cout << " Create a new HTTP server failure!" << std::endl;goto FREE_BASE;}evhttp_set_gencb(http_, CHttpServer::serverIoExec, (void*)this);sock_ = evhttp_bind_socket_with_handle(http_, "0.0.0.0", DEFAULT_LISTEN_PORT);if(nullptr == sock_){std::cout << "" << std::endl;goto FREE_HTTP;}event_base_dispatch(base_);	FREE_SOCK:if(http_ && sock_){evhttp_del_accept_socket(http_, sock_); sock_ = nullptr;}FREE_HTTP:if(http_){evhttp_free(http_); http_ = nullptr;}
FREE_BASE:if(base_){event_base_free(base_); base_ = nullptr;}}	void CHttpServer::loop()
{while(!isExit_){sleep(2);			//这里使用select精准时钟比较合理,待修改}
}int main(int argc, char *argv[])
{std::shared_ptr<CHttpServer> impl = std::make_shared<CHttpServer>();if(impl){impl->loop();}return 0;
}

2.2.2、 http_server.h

#ifndef HTTP_SERVER_H__
#define HTTP_SERVER_H__#include <evhttp.h>
#include <event2/thread.h>#include <thread>#define DEFAULT_LISTEN_PORT		( 12385 )
class CHttpServer {
public:CHttpServer();~CHttpServer();void loop();static void serverIoExec(struct evhttp_request *req, void *arg);private:int method_POST_io_process( struct evhttp_request *req );int method_GET_io_process(struct evhttp_request *req);int pic_video_test(struct evhttp_request *_req, const std::string &strPath, const char *strParms/*参数query*/);void serverDispatch();			/*loop pthread process*/struct event_base *base_;struct evhttp 	  *http_;struct evhttp_bound_socket * sock_;bool isExit_;std::thread *serverloopThread_;
};
#endif 

2.3、 编译

g++ *.cpp -I ./event ./libevent*.a -lpthread

2.4、 运行结果

2.4.1、测试POST

因为没有将jsoncpp移植到项目中,所以只是简单的测试响应的基本内容
在这里插入图片描述

2.4.2 、测试GET请求

该demo请求的是二进制流
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229115.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机操作系统-第十八天

目录 进程调度时机 补充知识 进程调度的方式 非剥夺调度方式 剥夺调度方式 进程的切换与过程 本节思维导图 进程调度时机 进程调度&#xff08;低级调度&#xff09;&#xff0c;即按照某种算法从就绪队列中选择一个进程为其分配处理机。 共有两种需要进行进程调度与…

基于junit4搭建自定义的接口自动化测试框架

随着业务的逐步稳定&#xff0c;对于接口的改动也会逐渐变少。更多的是对业务逻辑的优化&#xff0c;功能实现的完善。对于测试来说&#xff0c;重复繁琐的功能测试不仅效率低下&#xff0c;而且耗费一定的人力资源。笔者支持的信息流业务下的一个图文管理平台就是一个功能较为…

Lambda表达式的简单理解

1. 初识lambda表达式 Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。 Lambda 表达式&#xff08;Lambda exp…

广州华锐互动:VR煤矿特殊工种作业实训帮助提高矿工的操作技能和安全意识

VR煤矿特殊工种作业实训系统为煤矿企业培训提供了全方位的支持&#xff0c;帮助提高矿工的操作技能和安全意识&#xff0c;促进煤矿企业的安全生产。 首先&#xff0c;VR煤矿特殊工种作业实训系统可以提供逼真的虚拟操作环境&#xff0c;使矿工能够身临其境地感受各种工种的作业…

计算机网络 网络层上 | IP数据报,IP地址,ICMP,ARP等

文章目录 1 网络层的两个层面2 网络协议IP2.1 虚拟互联网络2.2 IP地址2.2.1 固定分类编址方式2.2.2 无分类编制CIDR2.2.3 MAC地址和IP地址区别 2.3 地址解析协议ARP2.3.1 解析过程 2.4 IP数据报格式 3 IP层转发分组流程4 国际控制报文协议ICMP4.1 ICMP格式结构4.2 分类4.2.1 差…

学习MS Dynamics AX 2012编程开发 2. X++语言

X是用于构建Dynamics AX功能的编程语言。X是一种与C类似的面向对象编程语言。 完成本章后&#xff0c;您将能够理解X语言&#xff1b;您将知道可用的数据类型是什么&#xff0c;如何创建各种循环&#xff0c;如何比较和操作变量&#xff0c;在哪里可以找到预定义的函数&#x…

【Android逆向】记录一次某某虚拟机的逆向

导语 学了一段时间的XPosed&#xff0c;发现XPosed真的好强&#xff0c;只要技术强&#xff0c;什么操作都能实现... 这次主要记录一下我对这款应用的逆向思路 apk检查 使用MT管理器检查apk的加壳情况 发现是某数字的免费版本 直接使用frida-dexdump 脱下来后备用 应用分…

二叉树前,中序推后续_中,后续推前序

文章目录 介绍思路例子 介绍 二叉树是由根、左子树、右子树三部分组成。 二叉树的遍历方式又可以分为前序遍历&#xff0c;中序遍历&#xff0c;后序遍历。 前序遍历&#xff1a;根&#xff0c;左子树&#xff0c;右子树 中序遍历&#xff1a;左子树&#xff0c;根&#xff0…

菜鸟学习日记(python)——匿名函数

Python 使用 lambda 来创建匿名函数。 lambda 函数是一种小型、匿名的内联函数&#xff0c;它可以具有任意数量的参数&#xff0c;但只能有一个表达式。 匿名函数的一般格式如下&#xff1a; lambda 参数列表:表达式 表达式用于计算并返回函数结果 lambda 函数通常用于编写…

FreeRtos里的几个中断屏蔽

1、primask 寄存器 PRIMASK用于禁止除NMI和HardFalut外的所有异常和中断&#xff0c;使用方法&#xff1a; cpsid i &#xff1b; //设置primask &#xff08;禁止中断&#xff09; cpsie i ; //清除primask (使能中断) 也可以 movs r0,#1 msr primask r0; //将 1写入p…

C# WPF上位机开发(网络程序界面开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前我们讨论过&#xff0c;设备之间通讯的方式很多。但是&#xff0c;不知道大家有没有注意&#xff0c;前面谈到的这些通讯方式都需要上位机电脑…

华为云创新动能涌现,浒墅关开启先进制造新纪元

编辑&#xff1a;阿冒 设计&#xff1a;沐由 穿境而过的京杭大运河&#xff0c;孕育了苏州浒墅关深厚的历史文化底蕴。千年延续不断的繁华&#xff0c;滋养了一代又一代奋进的浒墅关人。今天&#xff0c;一座国家级经开区挺立在这里&#xff0c;散发出创新创业的蓬勃活力。 苏州…

WordPress如何搭建多站点

这边之前有讲到过wordpress站中站&#xff08;栏目站&#xff09;建站教程&#xff0c;同样的也有讲到过WordPress开启多站点配置&#xff0c;两种方法都是用来搭建子站点的&#xff0c;而开启多站点的方式不同于普通搭建站中站&#xff0c;多站点配置开启&#xff0c;是可以实…

STM32F407-14.3.18-01连接霍尔传感器

连接霍尔传感器 可通过用于生成电机驱动 PWM 信号的高级控制定时器&#xff08;TIM1 或 TIM8&#xff09;以及图 114 中称为 “接口定时器”的另一个定时器 TIMx&#xff08;TIM2、TIM3、TIM4 或 TIM5&#xff09;&#xff0c;实现与霍尔传感器的连接。3 个定时器输入引脚&…

【C语言】实战项目——通讯录

引言 学会创建一个通讯录&#xff0c;对过往知识进行加深和巩固。 文章很长&#xff0c;要耐心学完哦&#xff01; ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》 &#x1f388;跟着猪巴戒&#xff0c;一起学习C语言&#x1f388; 目录 引言 实战 建…

C语言——完数难题(编程题目)

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 生命如同寓言&#xff0c;其价值不在于…

【数据分享】2019-2023年我国区县逐年二手房房价数据(Excel/Shp格式)

房价是一个区域发展程度的重要体现&#xff0c;一个区域的房价越高通常代表这个区域越发达&#xff0c;对于人口的吸引力越大&#xff01;因此&#xff0c;房价数据是我们在各项城市研究中都非常常用的数据&#xff01;之前我们分享了2019—2023年我国区县逐月的二手房房价数据…

破译模式:模式识别在计算机视觉中的作用

一、介绍 在当代数字领域&#xff0c;计算机视觉中的模式识别是关键的基石&#xff0c;推动着众多技术进步和应用。本文探讨了计算机视觉中模式识别的本质、方法、应用、挑战和未来趋势。通过使机器能够识别和解释视觉数据中的模式&#xff0c;模式识别不仅推动了计算机视觉领域…

小程序商城活动页面怎么生成二维码

背景 小程序商城某些页面需要做成活动推广页&#xff0c;或需要某一个页面做成二维码进行推广。比如某些非公开的商品做成一个活动&#xff0c;发送指定部分用户&#xff0c;这个活动页面可以做成二维码。 前提 小程序已经上线 步骤 登录微信小程序官网&#xff0c;选择工具…

【i.MX6ULL】使用buildroot构建根文件系统

文章目录 前言1、下载源码2、构建根文件系统1. 配置buildroot2. 编译buildroot3. buildroot根文件系统测试 3、buildroot第三方软件和库的配置1. 使能 alsa-lib2. 使能 alsa-utils 4、 buildroot下的busybox配置1. busybox配置2. 使能常用命令 前言 本篇文章时参考的正点原子的…