drogon/examples/simple_example_test/WebSocketCoroTest.cc
Martin Chang a2142dd93e
Coroutine support (#693)
* app().registerHttpHandler() accepts coroutine as handlers
* HttpController can use coroutine as handlers'
* Http request handlers with coroutine catches exception instead of crashing the entire app
* DbClient now has execSqlCoro that is awaitable
* DbClient now has newTransactionCoro that is awaitable
* HttpClient have awaitable sendRequestCoro
* WebSocketClient have awaitable connectToServerCoro
* WebSocketClient have setAsyncMessageHandler and setAsyncConnectionClosedHandler
* drogon::AsyncTask and drogon::Task<T> as our corutine types
* Related tests
* Misc

Future work
* Coroutine for WebSocket server
* Known issues

co_future() and sync_wait may crash. It looks like GCC bug but I'm not sure.
Workarround: Make an coroutine of AsyncTask. Then launch said coroutine.
Not sure why wrapping the exact same thing in function crashes things.

Co-authored-by: an-tao <antao2002@gmail.com>
2021-02-06 17:05:58 +08:00

81 lines
2.2 KiB
C++

#include <drogon/WebSocketClient.h>
#include <drogon/HttpAppFramework.h>
#include <trantor/net/EventLoopThread.h>
#include <iostream>
using namespace drogon;
using namespace std::chrono_literals;
Task<> doTest(WebSocketClientPtr wsPtr, HttpRequestPtr req, bool continually)
{
wsPtr->setAsyncMessageHandler(
[continually](std::string&& message,
const WebSocketClientPtr wsPtr,
const WebSocketMessageType type) -> Task<> {
std::cout << "new message:" << message << std::endl;
if (type == WebSocketMessageType::Pong)
{
std::cout << "recv a pong" << std::endl;
if (!continually)
{
app().getLoop()->quit();
}
}
co_return;
});
wsPtr->setAsyncConnectionClosedHandler(
[](const WebSocketClientPtr wsPtr) -> Task<> {
std::cout << "ws closed!" << std::endl;
co_return;
});
try
{
auto resp = co_await wsPtr->connectToServerCoro(req);
}
catch (...)
{
std::cout << "ws failed!" << std::endl;
if (!continually)
{
exit(1);
}
}
std::cout << "ws connected!" << std::endl;
wsPtr->getConnection()->setPingMessage("", 2s);
wsPtr->getConnection()->send("hello!");
}
int main(int argc, char* argv[])
{
auto wsPtr = WebSocketClient::newWebSocketClient("127.0.0.1", 8848);
auto req = HttpRequest::newHttpRequest();
req->setPath("/chat");
bool continually = true;
if (argc > 1)
{
if (std::string(argv[1]) == "-t")
continually = false;
else if (std::string(argv[1]) == "-p")
{
// Connect to a public web socket server.
wsPtr =
WebSocketClient::newWebSocketClient("wss://echo.websocket.org");
req->setPath("/");
}
}
app().getLoop()->runAfter(5.0, [continually]() {
if (!continually)
{
exit(1);
}
});
app().setLogLevel(trantor::Logger::kTrace);
[=]() -> AsyncTask { co_await doTest(wsPtr, req, continually); }();
app().run();
}