Реализация C ++ на стороне сервера?

Я пытаюсь реализовать сервер C ++ для генерации события для javascript EventSource, я создаю его с помощью cpprest. Из примеров, которые я видел в PHP или Node.js, это выглядело довольно просто, но я должен что-то упустить, так как я получаю это в консоли Firefox:

Firefox can’t establish a connection to the server at http://localhost:32123/data.

С почтальоном я правильно получаю "data : test" поэтому я думаю, что мне не хватает какого-то продолжения, возможно, мне нужно сделать что-то большее, чем просто ответить на запрос, но я не нашел хорошего объяснения того, как это должно работать. Если у вас есть какие-то документы, на которые вы могли бы указать, это было бы очень полезно!

Сценарий HTML-страницы выглядит следующим образом:

var source = new EventSource("http://localhost:32123/data");

source.onmessage = function (event) {
document.getElementById("result1").innerHTML += event.data + "<br>";
};

Ответ сервера C ++:

wResponse.set_status_code(status_codes::OK);
wResponse.headers().add(U("Access-Control-Allow-Origin"), U("*"));
wResponse.set_body(U("data: test"));
iRequest.reply(wResponse);

И запрос, который получает мой сервер:

GET /data HTTP/1.1
Accept: text/event-stream
Accept-Encoding: gzip, deflate
Accept-Language: en-us, en;q=0.5
Cache-Control: no-cache
Connection: keep-alive
Host: localhost:32123
Origin: null
Pragma: no-cache
User-Agent: Mozilla/5.0 (Windows NT6.1; Win64, x64; rv:61.0) Gecko/20100101 Firefox/61.0

1

Решение

Нашел решение здесь

Вот небольшое доказательство. Это не идеально, но работает. Следующий шаг — выяснить, как хранить соединения, проверять их наличие и т. Д.

РЕДАКТИРОВАТЬ: обновление ответа после комментария Даррена

Правильное решение, кажется, вращается вокруг кормления producer_consumer_buffer<char> привязан к basic_istream<uint8_t> это установлено как http_response тело.

Тогда как только http_request::reply сделано, соединение будет оставаться открытым, пока не будет закрыт буфер, что можно сделать с помощью wBuffer.close(std::ios_base::out).wait();,

Я не уверен на 100%, но кажется, что wBuffer.sync().wait(); действует как PHP flush Команда будет использоваться в аналогичном событийные обеспечение-сервер сценарий.

Рабочий пример был добавлен ниже.

Это не полное решение, очевидно. Впереди еще больше веселья с управлением соединениями и всем прочим. Создавая некоторые Connection с make_unique и хранение их в контейнере, который посещали на событиях, вероятно, будет моим способом …

main.cpp

#include "cpprest/uri.h"#include "cpprest/producerconsumerstream.h"#include "cpprest/http_listener.h"
using namespace std;
using namespace web;
using namespace http;
using namespace utility;
using namespace concurrency;
using namespace http::experimental::listener;

struct MyServer
{
MyServer(string_t url);
pplx::task<void> open()  { return mListener.open(); };
pplx::task<void> close() { return mListener.close(); };

private:

void handleGet(http_request iRequest);
http_listener mListener;
};

MyServer::MyServer(utility::string_t url) : mListener(url)
{
mListener.support(methods::GET, bind(&MyServer::handleGet, this, placeholders::_1));
}

void MyServer::handleGet(http_request iRequest)
{
ucout << iRequest.to_string() << endl;

http_response wResponse;

// Setting headers
wResponse.set_status_code(status_codes::OK);
wResponse.headers().add(header_names::access_control_allow_origin, U("*"));
wResponse.headers().add(header_names::content_type, U("text/event-stream"));

// Preparing buffer
streams::producer_consumer_buffer<char> wBuffer;
streams::basic_istream<uint8_t> wStream(wBuffer);
wResponse.set_body(wStream);

auto wReplyTask = iRequest.reply(wResponse);

wBuffer.putn_nocopy("data: a\n",10).wait();
wBuffer.putn_nocopy("data: b\n\n",12).wait();
wBuffer.sync().wait();  // seems equivalent to 'flush'

this_thread::sleep_for(chrono::milliseconds(2000));

wBuffer.putn_nocopy("data: c\n", 10).wait();
wBuffer.putn_nocopy("data: d\n\n", 12).wait();
wBuffer.sync().wait();
// wBuffer.close(std::ios_base::out).wait();    // closes the connection
wReplyTask.wait();      // blocking!
}

unique_ptr<MyServer> gHttp;

void onInit(const string_t iAddress)
{
uri_builder wUri(iAddress);
auto wAddress = wUri.to_uri().to_string();
gHttp = unique_ptr<MyServer>(new MyServer(wAddress));

gHttp->open().wait();
ucout << string_t(U("Listening for requests at: ")) << wAddress << endl;

}

void onShutdown()
{
gHttp->close().wait();
}void main(int argc, wchar_t* argv[])
{

onInit(U("http://*:32123"));

cout << "Wait until connection occurs..." << endl;
getchar();

onShutdown();
}

sse.htm

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="result"></div>
</body>
</html>

<script>

if (typeof (EventSource) !== undefined)
{
document.getElementById("result").innerHTML += "SSE supported" + "<br>";
}
else
{
document.getElementById("result").innerHTML += "SSE NOT supported" + "<br>";
}

var source = new EventSource("http://localhost:32123/");

source.onopen = function ()
{
document.getElementById("result").innerHTML += "open" + "<br>";
};

source.onerror = function ()
{
document.getElementById("result").innerHTML += "error" + "<br>";
};

source.onmessage = function (event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};

</script>
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]