绍兴市工程建设网站,流媒体网站建设规划,王烨这个名字怎么样,长沙3合1网站建设目录 1、前言2、测试demo2.1、目录结构2.2、 测试源码2.2.1、http_server.cpp2.2.2、 http_server.h 2.3、 编译2.4、 运行结果2.4.1、测试POST2.4.2 、测试GET请求 1、前言 项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信#xff0c;比较常用的使用POST和GET方式… 目录 1、前言2、测试demo2.1、目录结构2.2、 测试源码2.2.1、http_server.cpp2.2.2、 http_server.h 2.3、 编译2.4、 运行结果2.4.1、测试POST2.4.2 、测试GET请求 1、前言 项目开发中经常需要使用到私有协议和Qt,Android等GUI前端通信比较常用的使用POST和GET方式带出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.hCHttpServer::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;charsetUTF-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_ptrJson::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;charsetUTF-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_ptrCHttpServer impl std::make_sharedCHttpServer();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 -lpthread2.4、 运行结果
2.4.1、测试POST
因为没有将jsoncpp移植到项目中所以只是简单的测试响应的基本内容
2.4.2 、测试GET请求
该demo请求的是二进制流