直接上代码:测试过可用。需要下载libevent库搭配着使用。外加json开源库(也可以不用,去掉相关代码即可。)
// .h
#pragma once
class HttpServer
{
public:
HttpServer();
~HttpServer();
static HttpServer* Instance(){ return m_instance; }
void StartListen(int httpPort); // 监听端口
private:
int httpserver_bindsocket(int port, int backlog);
void* httpserver_Dispatch(void *arg);
bool Linsten(int httpPort);
private:
static HttpServer* m_instance;
class AutoDel
{
public:
~AutoDel()
{
if (m_instance != nullptr)
{
delete m_instance;
m_instance = nullptr;
}
}
};
static AutoDel m_del;
};
//.cpp
#include <time.h>
#include <thread>
#include <Winsock2.h>
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/http.h"
#include "evhttp.h"
#include "json\include\reader.h"
#include "json\include\writer.h"
#include "HttpServer.h"
// libevent库需要用到
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"AdvAPI32.lib")
#pragma comment(lib,"wsock32.lib")
bool GetRequest(struct evhttp_request *req, std::string &requestStr)
{
//WLog(LOG_DEBUG, "GetRequest threadId[%d] remoteHost[%s][%d]", std::this_thread::get_id(),req->remote_host, req->remote_port);
size_t postSize = EVBUFFER_LENGTH(req->input_buffer);
char *postData = (char *)EVBUFFER_DATA(req->input_buffer);
if (postSize > 0)
{
requestStr = std::string(postData, postSize);
return true;
}
requestStr = "data is null";
return false;
}
void Response(struct evhttp_request *req, const std::string &replyStr)
{
evbuffer *buff = evbuffer_new();
evbuffer_add_printf(buff, "%s", replyStr.c_str());
evhttp_send_reply(req, HTTP_OK, "OK", buff);
evbuffer_free(buff);
}
void RegistImage(struct evhttp_request *req, void *arg)
{
std::string requestStr, responseStr;
bool bsucc = false;
do
{
bsucc = GetRequest(req, requestStr);
if (bsucc)
{
Json::Reader reader;
Json::Value val;
bsucc = reader.parse(requestStr, val);
if (!bsucc)
{
//WLog(LOG_ERR, "regist fail, parse requestStr[%s] err", requestStr.c_str());
responseStr = "regist fail, parse requestStr err";
break;
}
std::string id = val["uid"].asString();
std::string name = val["name1"].asString();
std::string imgstr = val["image"].asString();
responseStr = "succ";
}
} while (0);
Json::FastWriter wr;
Json::Value wrVal;
wrVal["code"] = bsucc ? "0" : "-1";
wrVal["msg"] = bsucc ? "OK" : responseStr;
Response(req, wr.write(wrVal));
}
//--------------------http服务器类--------------------
HttpServer* HttpServer::m_instance = new HttpServer;
HttpServer::HttpServer()
{
// windows下必须使用此来初始化套接字
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
HttpServer::~HttpServer()
{
// 程序最后调用WSACleanup();释放资源
WSACleanup();
}
void HttpServer::StartListen(int httpPort)
{
std::thread t(&HttpServer::Linsten, this, httpPort);
t.detach();
}
bool HttpServer::Linsten(int httpPort)
{
int r, i;
int nfd = httpserver_bindsocket(httpPort, 10000);
if (nfd < 0)
{
return false;
}
std::vector<std::thread> threadVec;
for (i = 0; i < 20; i++)
{
struct event_base *base = event_base_new();
if (base == NULL)
{
continue;
}
struct evhttp *httpd = evhttp_new(base);
if (httpd == NULL)
{
event_base_free(base);
continue;
}
r = evhttp_accept_socket(httpd, nfd);
if (r != 0)
{
evhttp_free(httpd);
event_base_free(base);
continue;
}
evhttp_set_timeout(httpd, 10);
evhttp_set_cb(httpd, "/v1/face/register", RegistImage, NULL);
//evhttp_set_gencb(httpd, generic_handler, NULL);
threadVec.push_back(std::thread(&HttpServer::httpserver_Dispatch, this, base));
}
//WLog(LOG_INFO, "http server start at port:%d", httpPort);
for (i = 0; i < threadVec.size(); i++)
{
threadVec[i].join();
}
return true;
}
int HttpServer::httpserver_bindsocket(int port, int backlog)
{
int r;
int nfd;
nfd = socket(AF_INET, SOCK_STREAM, 0);
if (nfd < 0)
{
//WLog(LOG_ERR, "socket port[%d] ret[%d] err[%d]",port, nfd,GetLastError());
return nfd;
}
int one = 1;
r = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int));//设置端口复用
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
//addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
r = bind(nfd, (struct sockaddr*)&addr, sizeof(addr));
if (r < 0)
{
//WLog(LOG_ERR, "bind port[%d] ret[%d],err[%d]", port, r, WSAGetLastError());
return r;
}
r = listen(nfd, backlog);
if (r < 0)
{
//WLog(LOG_ERR, "listen port[%d] ret[%d],err[%d]", port, r, GetLastError());
return r;
}
//设置非阻塞
unsigned long flags = 1;
if (ioctlsocket(nfd, FIONBIO, &flags) < 0)
return -1;
return nfd;
}
void* HttpServer::httpserver_Dispatch(void *arg)
{
event_base_dispatch((struct event_base*)arg);
return NULL;
}
void* HttpServer::httpserver_Dispatch(void *arg)
{
event_base_dispatch((struct event_base*)arg);
return NULL;
}