在 win32 服务 (C++) 中生成 casablanca http_listener 的问题

Posted

技术标签:

【中文标题】在 win32 服务 (C++) 中生成 casablanca http_listener 的问题【英文标题】:Issues spawning a casablanca http_listener in a win32 service (C++) 【发布时间】:2020-05-13 11:55:04 【问题描述】:

由于某种原因,我无法在我的 Windows 服务主线程中启动我的侦听器,代码编译时没有警告并且我没有收到任何链接错误,cpprestsdk DLL 由进程正确加载(使用 procmon 验证)但是,听众不是在“听”:-)。该服务作为 NT AUTHORITY\SYSTEM 运行。在 win32 服务(x64 架构)中运行它是否有任何限制:

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)

    //
    //  Periodically check if the service has been requested to stop
    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
    
        /*
        * Perform main service function here
        */

        webserver();
    

    return ERROR_SUCCESS;

这里是 webserver() 的实现:

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <map>
#include <set>
#include <string>

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
using namespace std;

void handle_GET(http_request message)

    message.reply(status_codes::OK, "<html><body><h1>Hello World !</h1></body></html>", u8"text/html");
    return;


void webserver()

    http_listener listener(L"http://127.0.0.1/api");
    listener.support(methods::GET, handle_GET);
    listener.open().wait();

如果我简单地将它编译为普通的可执行文件并从 main() 运行它,这个函数就可以工作...

任何想法为什么我会出现这种奇怪的行为?

PS:即使监听器不工作,服务也能正确启动和停止。我正在使用这个框架 Windows 服务模板 (Windows Service Template)

我正在使用 Microsoft Visual Studio 2017 编译所有内容。

编辑:通过禁用防火墙并以管理员权限运行 netstat,该服务似乎正在侦听 127.0.0.1 地址上的端口 80,但是我仍然没有收到 HTTP 响应并且运行“netstat -an | findstr 80”时,监听端口似乎会打开和关闭:

Screenshot

【问题讨论】:

您在哪个服务帐户下运行?有些帐户没有网络访问权限。 嗨,它正在使用 SYSTEM 帐户运行。 阅读 - ***.com/questions/10942916/… 有趣,但在我的情况下,它不是防火墙,因为当我运行“netstat -a”并且我试图通过环回地址(127.0.0.1)连接时,端口甚至没有绑定像这样:“wget 127.0.0.1:80/api” 我的错误,如果我禁用防火墙和杀毒软件,端口正在监听...但是,http 请求没有得到任何响应。 【参考方案1】:

好的,我最终这样做了,这似乎“解决”了这个问题:

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <map>
#include <set>
#include <string>
#include <Windows.h>

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
using namespace std;

void handle_GET(http_request message)

    message.reply(status_codes::OK, "<html><body><h1>Hello World !</h1></body></html>", u8"text/html");
    return;


void webserver()

    http_listener listener(L"http://127.0.0.1/api");
    listener.support(methods::GET, handle_GET);
    listener.open().wait();
    ::Sleep(1000000000000000000);

但我认为这很讨厌,我怀疑它只是根据睡眠时间来回摆动...

#include "api.h"
#include <thread>
#include "ServiceWorkerThread.h"

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)

    //
    //  Periodically check if the service has been requested to stop
    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
    
        /*
        * Perform main service function here
        */
        webserver();
    

    return ERROR_SUCCESS;

关于如何做这个清洁剂的任何建议?

解决方案:我最终像这样更改代码:

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <map>
#include <set>
#include <string>
#include <Windows.h>
#include "ServiceWorkerThread.h"

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
using namespace std;

void handle_GET(http_request message)

    message.reply(status_codes::OK, "<html><body><h1>Hello World !</h1></body></html>", u8"text/html");
    return;


long webserver()

    http_listener listener(L"http://127.0.0.1/api");
    listener.support(methods::GET, handle_GET);
    listener.open().wait();
    //
//  Periodically check if the service has been requested to stop
    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
    
        /*
        * Perform main service function here
        */
    

    return ERROR_SUCCESS;


#include "api.h"
#include <thread>
#include "ServiceWorkerThread.h"

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)

    long ret = webserver();
    return ret;

除了在 Windows 防火墙中例外...

【讨论】:

欢迎accept your own answer。

以上是关于在 win32 服务 (C++) 中生成 casablanca http_listener 的问题的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中生成任意嵌套的向量

如何在 C++ 中生成随机数?

如何在 C++ 中生成 mhtml 文件? [关闭]

在 C++ 中生成三个字母[关闭]

使用 c++ 在 OpenGL 中生成两个对象

为啥在同一个 Visual Studio 解决方案中生成 C++ 调试符号不匹配?