一、安装libevent
下载编译安装,提前安装好gcc, make
sudo su
yum -y install wget
wget http://www.monkey.org/~provos/libevent-2.0.10-stable.tar.gz
tar -zxvf libevent-2.0.10-stable.tar.gz
cd libevent-2.0.10-stable
./configure --prefix=/usr
make -j2
make install
# 查看安装结果
ls -al /usr/lib | grep libevent
安装后的输出信息,
make install-recursive
make[1]: Entering directory `/home/username/libevent-2.0.10-stable'
Making install in .
make[2]: Entering directory `/home/username/libevent-2.0.10-stable'
make[3]: Entering directory `/home/username/libevent-2.0.10-stable'
test -z "/usr/bin" || /usr/bin/mkdir -p "/usr/bin"
/usr/bin/install -c event_rpcgen.py '/usr/bin'
test -z "/usr/lib" || /usr/bin/mkdir -p "/usr/lib"
/bin/sh ./libtool --mode=install /usr/bin/install -c libevent.la libevent_core.la libevent_extra.la libevent_pthreads.la libevent_openssl.la '/usr/lib'
libtool: install: /usr/bin/install -c .libs/libevent-2.0.so.5.0.1 /usr/lib/libevent-2.0.so.5.0.1
libtool: install: (cd /usr/lib && { ln -s -f libevent-2.0.so.5.0.1 libevent-2.0.so.5 || { rm -f libevent-2.0.so.5 && ln -s libevent-2.0.so.5.0.1 libevent-2.0.so.5; }; })
libtool: install: (cd /usr/lib && { ln -s -f libevent-2.0.so.5.0.1 libevent.so || { rm -f libevent.so && ln -s libevent-2.0.so.5.0.1 libevent.so; }; })
libtool: install: /usr/bin/install -c .libs/libevent.lai /usr/lib/libevent.la
libtool: install: /usr/bin/install -c .libs/libevent_core-2.0.so.5.0.1 /usr/lib/libevent_core-2.0.so.5.0.1
libtool: install: (cd /usr/lib && { ln -s -f libevent_core-2.0.so.5.0.1 libevent_core-2.0.so.5 || { rm -f libevent_core-2.0.so.5 && ln -s libevent_core-2.0.so.5.0.1 libevent_core-2.0.so.5; }; })
libtool: install: (cd /usr/lib && { ln -s -f libevent_core-2.0.so.5.0.1 libevent_core.so || { rm -f libevent_core.so && ln -s libevent_core-2.0.so.5.0.1 libevent_core.so; }; })
libtool: install: /usr/bin/install -c .libs/libevent_core.lai /usr/lib/libevent_core.la
libtool: install: /usr/bin/install -c .libs/libevent_extra-2.0.so.5.0.1 /usr/lib/libevent_extra-2.0.so.5.0.1
libtool: install: (cd /usr/lib && { ln -s -f libevent_extra-2.0.so.5.0.1 libevent_extra-2.0.so.5 || { rm -f libevent_extra-2.0.so.5 && ln -s libevent_extra-2.0.so.5.0.1 libevent_extra-2.0.so.5; }; })
libtool: install: (cd /usr/lib && { ln -s -f libevent_extra-2.0.so.5.0.1 libevent_extra.so || { rm -f libevent_extra.so && ln -s libevent_extra-2.0.so.5.0.1 libevent_extra.so; }; })
libtool: install: /usr/bin/install -c .libs/libevent_extra.lai /usr/lib/libevent_extra.la
libtool: install: /usr/bin/install -c .libs/libevent_pthreads-2.0.so.5.0.1 /usr/lib/libevent_pthreads-2.0.so.5.0.1
libtool: install: (cd /usr/lib && { ln -s -f libevent_pthreads-2.0.so.5.0.1 libevent_pthreads-2.0.so.5 || { rm -f libevent_pthreads-2.0.so.5 && ln -s libevent_pthreads-2.0.so.5.0.1 libevent_pthreads-2.0.so.5; }; })
libtool: install: (cd /usr/lib && { ln -s -f libevent_pthreads-2.0.so.5.0.1 libevent_pthreads.so || { rm -f libevent_pthreads.so && ln -s libevent_pthreads-2.0.so.5.0.1 libevent_pthreads.so; }; })
libtool: install: /usr/bin/install -c .libs/libevent_pthreads.lai /usr/lib/libevent_pthreads.la
libtool: install: /usr/bin/install -c .libs/libevent_openssl-2.0.so.5.0.1 /usr/lib/libevent_openssl-2.0.so.5.0.1
libtool: install: (cd /usr/lib && { ln -s -f libevent_openssl-2.0.so.5.0.1 libevent_openssl-2.0.so.5 || { rm -f libevent_openssl-2.0.so.5 && ln -s libevent_openssl-2.0.so.5.0.1 libevent_openssl-2.0.so.5; }; })
libtool: install: (cd /usr/lib && { ln -s -f libevent_openssl-2.0.so.5.0.1 libevent_openssl.so || { rm -f libevent_openssl.so && ln -s libevent_openssl-2.0.so.5.0.1 libevent_openssl.so; }; })
libtool: install: /usr/bin/install -c .libs/libevent_openssl.lai /usr/lib/libevent_openssl.la
libtool: install: /usr/bin/install -c .libs/libevent.a /usr/lib/libevent.a
libtool: install: chmod 644 /usr/lib/libevent.a
libtool: install: ranlib /usr/lib/libevent.a
libtool: install: /usr/bin/install -c .libs/libevent_core.a /usr/lib/libevent_core.a
libtool: install: chmod 644 /usr/lib/libevent_core.a
libtool: install: ranlib /usr/lib/libevent_core.a
libtool: install: /usr/bin/install -c .libs/libevent_extra.a /usr/lib/libevent_extra.a
libtool: install: chmod 644 /usr/lib/libevent_extra.a
libtool: install: ranlib /usr/lib/libevent_extra.a
libtool: install: /usr/bin/install -c .libs/libevent_pthreads.a /usr/lib/libevent_pthreads.a
libtool: install: chmod 644 /usr/lib/libevent_pthreads.a
libtool: install: ranlib /usr/lib/libevent_pthreads.a
libtool: install: /usr/bin/install -c .libs/libevent_openssl.a /usr/lib/libevent_openssl.a
libtool: install: chmod 644 /usr/lib/libevent_openssl.a
libtool: install: ranlib /usr/lib/libevent_openssl.a
libtool: finish: PATH="/opt/rh/devtoolset-8/root/usr/bin:/home/username/cmake-3.23.4-linux-x86_64/bin:/opt/rh/devtoolset-8/root/usr/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/username/.local/bin:/home/username/bin:/sbin" ldconfig -n /usr/lib
----------------------------------------------------------------------
Libraries have been installed in:
/usr/lib
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
[username@localhost libevent-2.0.10-stable]$ ls -al /usr/lib | grep libevent
lrwxrwxrwx. 1 root root 21 Jul 26 13:26 libevent-2.0.so.5 -> libevent-2.0.so.5.0.1
-rwxr-xr-x. 1 root root 1246224 Jul 26 13:26 libevent-2.0.so.5.0.1
-rw-r--r--. 1 root root 2204618 Jul 26 13:26 libevent.a
lrwxrwxrwx. 1 root root 26 Jul 26 13:26 libevent_core-2.0.so.5 -> libevent_core-2.0.so.5.0.1
-rwxr-xr-x. 1 root root 770744 Jul 26 13:26 libevent_core-2.0.so.5.0.1
-rw-r--r--. 1 root root 1323706 Jul 26 13:26 libevent_core.a
-rwxr-xr-x. 1 root root 975 Jul 26 13:26 libevent_core.la
lrwxrwxrwx. 1 root root 26 Jul 26 13:26 libevent_core.so -> libevent_core-2.0.so.5.0.1
lrwxrwxrwx. 1 root root 27 Jul 26 13:26 libevent_extra-2.0.so.5 -> libevent_extra-2.0.so.5.0.1
-rwxr-xr-x. 1 root root 501664 Jul 26 13:26 libevent_extra-2.0.so.5.0.1
-rw-r--r--. 1 root root 880986 Jul 26 13:26 libevent_extra.a
-rwxr-xr-x. 1 root root 982 Jul 26 13:26 libevent_extra.la
lrwxrwxrwx. 1 root root 27 Jul 26 13:26 libevent_extra.so -> libevent_extra-2.0.so.5.0.1
-rwxr-xr-x. 1 root root 940 Jul 26 13:26 libevent.la
lrwxrwxrwx. 1 root root 29 Jul 26 13:26 libevent_openssl-2.0.so.5 -> libevent_openssl-2.0.so.5.0.1
-rwxr-xr-x. 1 root root 117392 Jul 26 13:26 libevent_openssl-2.0.so.5.0.1
-rw-r--r--. 1 root root 217556 Jul 26 13:26 libevent_openssl.a
-rwxr-xr-x. 1 root root 1011 Jul 26 13:26 libevent_openssl.la
lrwxrwxrwx. 1 root root 29 Jul 26 13:26 libevent_openssl.so -> libevent_openssl-2.0.so.5.0.1
lrwxrwxrwx. 1 root root 30 Jul 26 13:26 libevent_pthreads-2.0.so.5 -> libevent_pthreads-2.0.so.5.0.1
-rwxr-xr-x. 1 root root 26440 Jul 26 13:26 libevent_pthreads-2.0.so.5.0.1
-rw-r--r--. 1 root root 26454 Jul 26 13:26 libevent_pthreads.a
-rwxr-xr-x. 1 root root 1003 Jul 26 13:26 libevent_pthreads.la
lrwxrwxrwx. 1 root root 30 Jul 26 13:26 libevent_pthreads.so -> libevent_pthreads-2.0.so.5.0.1
lrwxrwxrwx. 1 root root 21 Jul 26 13:26 libevent.so -> libevent-2.0.so.5.0.1
二、安装jsoncpp
开源地址:https://github.com/open-source-parsers/jsoncpp
wget https://github.com/open-source-parsers/jsoncpp/archive/refs/tags/1.9.4.tar.gz
tar -zxvf 1.9.4.tar.gz
cd jsoncpp-1.9.4/
mkdir build && cd build/
cmake -DCMAKE_BUILD_TYPE=release \
-DBUILD_STATIC_LIBS=ON \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_INSTALL_INCLUDEDIR=/usr/include/jsoncpp \
-DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" ../
make -j2
sudo make install
[username@localhost build]$ sudo make install
[sudo] password for username:
Consolidate compiler generated dependencies of target jsoncpp_lib
[ 23%] Built target jsoncpp_lib
Consolidate compiler generated dependencies of target jsoncpp_static
[ 47%] Built target jsoncpp_static
Consolidate compiler generated dependencies of target jsoncpp_object
[ 64%] Built target jsoncpp_object
Consolidate compiler generated dependencies of target jsontestrunner_exe
[ 76%] Built target jsontestrunner_exe
Consolidate compiler generated dependencies of target jsoncpp_test
[100%] Built target jsoncpp_test
Install the project...
-- Install configuration: "release"
-- Installing: /usr/local/lib64/pkgconfig/jsoncpp.pc
-- Installing: /usr/local/lib64/cmake/jsoncpp/jsoncppConfig.cmake
-- Installing: /usr/local/lib64/cmake/jsoncpp/jsoncppConfig-release.cmake
-- Installing: /usr/local/lib64/cmake/jsoncpp/jsoncppConfigVersion.cmake
-- Installing: /usr/local/lib64/libjsoncpp.so.1.9.4
-- Installing: /usr/local/lib64/libjsoncpp.so.24
-- Installing: /usr/local/lib64/libjsoncpp.so
-- Installing: /usr/local/lib64/libjsoncpp_static.a
-- Installing: /usr/local/lib64/objects-release/jsoncpp_object/json_reader.cpp.o
-- Installing: /usr/local/lib64/objects-release/jsoncpp_object/json_value.cpp.o
-- Installing: /usr/local/lib64/objects-release/jsoncpp_object/json_writer.cpp.o
-- Installing: /usr/include/jsoncpp/json/allocator.h
-- Installing: /usr/include/jsoncpp/json/assertions.h
-- Installing: /usr/include/jsoncpp/json/config.h
-- Installing: /usr/include/jsoncpp/json/forwards.h
-- Installing: /usr/include/jsoncpp/json/json.h
-- Installing: /usr/include/jsoncpp/json/json_features.h
-- Installing: /usr/include/jsoncpp/json/reader.h
-- Installing: /usr/include/jsoncpp/json/value.h
-- Installing: /usr/include/jsoncpp/json/version.h
-- Installing: /usr/include/jsoncpp/json/writer.h
配置库目录
vim ~/.bashrc
export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib64:$LD_LIBRARY_PATH
source ~/.bashrc
三、http多线程服务
#pragma once
#include <event.h>
#include <evhttp.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <list>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <cstdlib>
#include <jsoncpp/json/json.h>
using namespace std;
#define LOG_DBG printf
#define LOG_INFO printf
#define LOG_WARN printf
#define LOG_ERR printf
namespace servers
{
class HttpSrv
{
public:
HttpSrv() {}
~HttpSrv() {}
bool start(int port, int nthreads);
bool stop();
protected:
struct WorkRoom {
HttpSrv* pSrv;
struct event_base* base;
struct evhttp* httpd;
struct event* watchdogEv;
bool dispatchStop = false;
};
list<WorkRoom*> workRoomList;
vector<thread> mWorkThList;
bool mIsExit = false;
static void watchdog(int fd, short event, void* argv);
void Dispatch(void* arg);
static void GenericHandler(struct evhttp_request* req, void* arg);
static void ProcessRequest(struct evhttp_request* request, void* arg);
static void HandlePostRequest(struct evhttp_request* request, void* arg);
int BindSocket(int port);
};
int HttpSrv::BindSocket(int port)
{
int r;
int nfd;
nfd = socket(AF_INET, SOCK_STREAM, 0);
if (nfd < 0) return -1;
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) return -1;
r = listen(nfd, 10240);
if (r < 0) return -1;
int flags;
if ((flags = fcntl(nfd, F_GETFL, 0)) < 0 || fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) return -1;
return nfd;
}
bool HttpSrv::start(int port, int nthreads) {
int r;
int nfd = BindSocket(port);//监听端口
if (nfd < 0) return false;
for (int i = 0; i < nthreads; i++)
{
WorkRoom* w = new WorkRoom;//每个线程独有的环境参数,不使用局部变量,防止离开局部作用域后失效
w->pSrv = this;
w->base = event_init(); //libevnet使用多线程,每个线程中使用一个base
if (w->base == NULL) return false;
w->httpd = evhttp_new(w->base);//初始化http
if (w->httpd == NULL) return false;
r = evhttp_accept_socket(w->httpd, nfd);
if (r != 0) return false;
evhttp_set_gencb(w->httpd, GenericHandler, this); //设置http路由 404
evhttp_set_cb(w->httpd, "/test", ProcessRequest, this); //设置http路由
evhttp_set_cb(w->httpd, "/image", HandlePostRequest, this); //设置http路由
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
event* watchdogEv = event_new(w->base, -1, EV_PERSIST | EV_TIMEOUT, watchdog, w);//每个base设置一个看门狗,可以做一些线程监控的工作
w->watchdogEv = watchdogEv;
event_add(watchdogEv, &tv);
mWorkThList.push_back(std::thread(std::bind(&HttpSrv::Dispatch, this, std::placeholders::_1), w)); //启动事件分发
workRoomList.push_back(w);//线程环境变量收集,善后处理
}
LOG_INFO("http start port:%d, thNum:%d\n", port, nthreads);
return true;
}
bool HttpSrv::stop() {
mIsExit = true;
while (workRoomList.size() > 0) {
for (auto w : workRoomList) {
if (!w->dispatchStop) {
continue;
}
if (w->watchdogEv) {
event_free(w->watchdogEv);
w->watchdogEv = nullptr;
}
if (w->httpd) {
evhttp_free(w->httpd);
w->httpd = nullptr;
}
if (w->base) {
event_base_free(w->base);
w->base = nullptr;
}
workRoomList.remove(w);
delete w;
break;
}
}
for (auto& t : mWorkThList) {
if (t.joinable()) {
t.join();
}
}
return true;
}
void HttpSrv::Dispatch(void* arg) {
LOG_DBG("dispatch start\n");
WorkRoom* w = (WorkRoom*)arg;
event_base_dispatch(w->base);
LOG_DBG("dispatch stop\n");
w->dispatchStop = true;
}
void HttpSrv::watchdog(int fd, short event, void* argv) {
WorkRoom* w = (WorkRoom*)argv;
HttpSrv* pSrv = w->pSrv;
if (pSrv->mIsExit) {
struct timeval delay = { 0, 1 };
event_base_loopexit(w->base, &delay);
}
}
void HttpSrv::GenericHandler(struct evhttp_request* req, void* arg)
{
((HttpSrv*)arg)->ProcessRequest(req, arg);
}
void HttpSrv::ProcessRequest(struct evhttp_request* req, void* arg)
{
// sleep(1);
struct evbuffer* buf = evbuffer_new();
if (buf == NULL)
return;
evbuffer_add_printf(buf, "Requested: %s\n", evhttp_request_uri(req));
evhttp_send_reply(req, HTTP_OK, "OK", buf);
}
void HttpSrv::HandlePostRequest(struct evhttp_request* req, void* arg)
{
// Get URI
const char* uri = evhttp_request_uri(req);
// Parse URI
struct evkeyvalq params;
evhttp_parse_query(uri, ¶ms);
// Get parameters
const char* key = evhttp_find_header(¶ms, "key");
const char* key2 = evhttp_find_header(¶ms, "key2");
// Check if parameters are present
if (key != NULL) {
// Process key
// ...
return;
}
if (key2 != NULL) {
// Process key2
// ...
return;
}
size_t len = evbuffer_get_length(req->input_buffer);
char* data = (char*)malloc(len);
evbuffer_remove(req->input_buffer, data, len);
Json::Reader reader;
Json::Value json;
if (!reader.parse(data, json)) {
// Handle error
return;
}
// Process JSON data
// ...
// Create response
Json::Value response;
response["status"] = "success";
Json::FastWriter writer;
std::string output = writer.write(response);
struct evbuffer* buf = evbuffer_new();
evbuffer_add(buf, output.c_str(), output.size());
evhttp_send_reply(req, HTTP_OK, "OK", buf);
free(data);
}
}
int main()
{
servers::HttpSrv s;
s.start(8080, 5);
sleep(60);
LOG_INFO("http to stop\n");
s.stop();
LOG_INFO("http stop\n");
}