Вот мой крошечный http-сервер, основанный на libevent;
#include "fmt/format.h"
#include <cstdint>
#include <cstdio>
#include <event2/event-config.h>
#include <event2/util.h>
#include <evhttp.h>
#include <memory>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <type_traits>
#include <unistd.h>
auto
main() -> int
{
constexpr char host[] = "127.0.0.1";
constexpr std::uint16_t port = 5555;
using event_base_new_type
= std::pointer_traits<decltype(event_base_new())>::element_type;
using event_base_deleter_type = decltype(&event_base_free);
auto event_base
= std::unique_ptr<event_base_new_type, event_base_deleter_type>(
event_base_new(), &event_base_free);
if(!(event_base))
{
fmt::print(stderr, "Failed to init libevent.\n");
return -1;
}
using evhttp_new_type = std::pointer_traits<decltype(
evhttp_new(event_base.get()))>::element_type;
using evhttp_deleter_type = decltype(&evhttp_free);
auto http = std::unique_ptr<evhttp_new_type, evhttp_deleter_type>(
evhttp_new(event_base.get()), &evhttp_free);
auto handle = evhttp_bind_socket_with_handle(http.get(), host, port);
if(!handle)
{
fmt::print(stderr, "Failed to init http server.\n");
return -1;
}
auto callback = [](evhttp_request* req, void*) {
auto* OutBuf = evhttp_request_get_output_buffer(req);
if(!OutBuf)
return;
evbuffer_add_printf(OutBuf,
"<html><body><center><h1>Hello World!</h1></center></body></html>");
evhttp_send_reply(req, HTTP_OK, "", OutBuf);
};
evhttp_set_gencb(http.get(), callback, nullptr);
if(event_base_dispatch(event_base.get()) == -1)
{
fmt::print(stderr, "Failed to run messahe loop.\n");
return -1;
}
return 0;
}
- Компиляция:
g++ a.cpp -lfmt -levent
- run:
./a.out
- browser:
http://127.0.0.1:5555
Я пытаюсь запустить эту программу как демон, чтобы я мог включить ее в свои тестовые сценарии ctest.
Я пробовал эту эту статью , вот мой код:
#include "fmt/format.h"
#include <cstdint>
#include <cstdio>
#include <event2/event-config.h>
#include <event2/util.h>
#include <evhttp.h>
#include <memory>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <type_traits>
#include <unistd.h>
static void
skeleton_daemon()
{
pid_t pid;
/* Fork off the parent process */
pid = fork();
/* An error occurred */
if(pid < 0)
exit(EXIT_FAILURE);
/* Success: Let the parent terminate */
if(pid > 0)
exit(EXIT_SUCCESS);
/* On success: The child process becomes session leader */
if(setsid() < 0)
exit(EXIT_FAILURE);
/* Catch, ignore and handle signals */
// TODO: Implement a working signal handler */
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
/* Fork off for the second time*/
pid = fork();
/* An error occurred */
if(pid < 0)
exit(EXIT_FAILURE);
/* Success: Let the parent terminate */
if(pid > 0)
exit(EXIT_SUCCESS);
/* Set new file permissions */
umask(0);
/* Change the working directory to the root directory */
/* or another appropriated directory */
chdir("/");
/* Close all open file descriptors */
int x;
for(x = sysconf(_SC_OPEN_MAX); x >= 0; x--)
{
close(x);
}
/* Open the log file */
openlog("firstdaemon", LOG_PID, LOG_DAEMON);
}
auto
main() -> int
{
constexpr char host[] = "127.0.0.1";
constexpr std::uint16_t port = 5555;
using event_base_new_type
= std::pointer_traits<decltype(event_base_new())>::element_type;
using event_base_deleter_type = decltype(&event_base_free);
auto event_base
= std::unique_ptr<event_base_new_type, event_base_deleter_type>(
event_base_new(), &event_base_free);
if(!(event_base))
{
fmt::print(stderr, "Failed to init libevent.\n");
return -1;
}
using evhttp_new_type = std::pointer_traits<decltype(
evhttp_new(event_base.get()))>::element_type;
using evhttp_deleter_type = decltype(&evhttp_free);
auto http = std::unique_ptr<evhttp_new_type, evhttp_deleter_type>(
evhttp_new(event_base.get()), &evhttp_free);
auto handle = evhttp_bind_socket_with_handle(http.get(), host, port);
if(!handle)
{
fmt::print(stderr, "Failed to init http server.\n");
return -1;
}
auto callback = [](evhttp_request* req, void*) {
auto* OutBuf = evhttp_request_get_output_buffer(req);
if(!OutBuf)
return;
evbuffer_add_printf(OutBuf,
"<html><body><center><h1>Hello World!</h1></center></body></html>");
evhttp_send_reply(req, HTTP_OK, "", OutBuf);
};
evhttp_set_gencb(http.get(), callback, nullptr);
skeleton_daemon();
while(1)
{
// TODO: Insert daemon code here.
if(event_base_dispatch(event_base.get()) == -1)
{
fmt::print(stderr, "Failed to run messahe loop.\n");
return -1;
}
syslog(LOG_NOTICE, "First daemon started.");
sleep(1000);
break;
}
syslog(LOG_NOTICE, "First daemon terminated.");
closelog();
return 0;
}
Но «Привет мир» не может быть отображен. Как исправить или есть более приятное решение?