0

I need to set up an application that listens on a number of Urls but do not know when I start how many - this will eventually be read from a database but for the moment they are hard coded in a demo.

// MultipleListenerTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <vector>

#include <cpprest\http_listener.h>
#include <cpprest\http_client.h>

#include "TestListener.h"               // listener object

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

void SetListenerArray();

typedef std::vector<http_listener> httpListeners;

listenerCollection listeners;

TestListener listener1;
TestListener Listener2;
TestListener Listener3;

httpListeners httpListenersList;
void handle_get(http_request request);
void handle_post(http_request request);
void handle_put(http_request request);
void handle_del(http_request request);


int _tmain(int argc, _TCHAR* argv[])
{

    SetListenerArray();

    for each (TestListener tl  in listeners)
    {
        http_listener l(tl.GetUrl());

        l.support(methods::GET, handle_get);
        l.support(methods::POST, handle_post);
        l.support(methods::PUT, handle_put);
        l.support(methods::DEL, handle_del);

        l.open().wait();
        httpListenersList.push_back(l);
    }

    std::string line;
    std::cout << "Press enter to exit" << std::endl;
    std::getline(std::cin, line);

    //listenerVoices_1.close().wait();
    //listenerVoices_2.close().wait();

    return 0;
}

void SetListenerArray()
{

    // first listener
    listener1.SetListenerName(to_string_t("FirstListener"));
    listener1.SetUrl(to_string_t("http://localhost:8010"));
    listeners.push_back(listener1);

    // second listener
    Listener2.SetListenerName(to_string_t("Second Listener"));
    Listener2.SetUrl(to_string_t("http://localhost:8020"));
    listeners.push_back(Listener2);

    //third listener
    Listener3.SetListenerName(to_string_t("Third Listener"));
    Listener3.SetUrl(to_string_t("http://localhost:8030"));
    listeners.push_back(Listener3);

}

void handle_get(http_request request)
{
    for each (TestListener tl  in listeners)
    {
        std::cout << to_utf8string(tl.GetListenerName());
    }
}

void handle_post(http_request request)
{

}

void handle_put(http_request request)
{

}

void handle_del(http_request request)
{

}

With the above code the line

httpListenersList.push_back(l);

fails to compile with the error

Error 1 error C2248: 'web::http::experimental::listener::http_listener::http_listener' : cannot access private member declared in class 'web::http::experimental::listener::http_listener' c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 593 1 MultipleListenerTest

If I leave it out then none of the listeners are actually listening and you get This webpage is not available in Chrome at least.

So how can you set up multiple listeners when you do not know before hand how many are required?

4

1 回答 1

2

使用线程 - 每个线程执行一个侦听器。

以下是执行侦听器的类中的方法。

void Listener::Start()
{
    Logger logger;
    std::string logMessage("Starting '" + to_utf8string(GetName()) + "' Listener");
    http_listener httpListener(GetUri());
    std::string listenerName(to_utf8string(name));

    logger.log(logMessage);

    // listener recieves a GET request.
    httpListener.support(methods::GET, [listenerName](http_request request)
    {
        Logger logger;

        std::string logMessage("GET request recieved from " + listenerName);

        logger.log(logMessage);

        // dummy line just till routing is dealt with
        request.reply(status_codes::OK, logMessage);

    });

    // open listener and route request 
    httpListener
        .open()
        .then([&httpListener,listenerName](){ 
            Logger logger;
            std::string logMessage(listenerName + " started");

            logger.log(logMessage);

        }).wait();

    // JUST WAIT - we do not want the application to stop
    while (true);

}

然后在程序中执行以下代码,它将所有侦听器收集在一个向量中。

然后扫描向量以创建每个线程。

RouteMaps rm;
Logger logger;
Listeners ls;
std::vector<std::thread> listener_threads;
std::vector<Listener> lvector;

std::cout.sync_with_stdio(true);

// collect all the listeners into a vector

for (auto& m : rm.Select()) {
    for (auto& l : ls.Select(m.GetId())) {
        std::string logMessage("Retrieved Listener " + to_utf8string(l.GetName()));
        logger.log(logMessage);
        lvector.push_back(l);
    }
}

std::cout << "Starting listeners" << std::endl;
// now create threads for each listener
for (auto& lstnr : lvector)
{
    listener_threads.push_back(std::thread{ &Listener::Start, &lstnr });
}

然而,应用程序将通过并结束 - 停止每个线程。现在在每个线程的底部都有一个永久循环 - 这意味着实际上没有线程会结束。

为了停止程序执行杀死每个线程,他们需要通过以下循环加入主线程。

for (auto& t : listener_threads)
{
    t.join();
}

通过这种方式,我们现在有多个线程,您不必在代码中定义有多少。

现在,当我将每个侦听器的域放在浏览器中时,我们会收到每个侦听器的回复。

于 2015-04-05T21:47:43.493 回答