drogon: Websocket not connected to server in native

#include <drogon/WebSocketClient.h>
#include <drogon/WebSocketController.h>
#include <drogon/HttpAppFramework.h>
#include <trantor/net/EventLoopThread.h>

#include <iostream>

using namespace drogon;
using namespace std::chrono_literals;

class WebSocketTest : public drogon::WebSocketController<WebSocketTest> {
public:
    virtual void handleNewMessage(const WebSocketConnectionPtr &,
                                  std::string &&,
                                  const WebSocketMessageType &) override;

    virtual void handleConnectionClosed(
            const WebSocketConnectionPtr &) override;

    virtual void handleNewConnection(const HttpRequestPtr &,
                                     const WebSocketConnectionPtr &) override;

    WS_PATH_LIST_BEGIN
    WS_PATH_ADD("/chat", "drogon::LocalHostFilter", Get);
    WS_PATH_LIST_END
};


void WebSocketTest::handleNewMessage(const WebSocketConnectionPtr &wsConnPtr,
                                     std::string &&message,
                                     const WebSocketMessageType &type) {
    // write your application logic here
    LOG_DEBUG << "new websocket message:" << message;
    if (type == WebSocketMessageType::Ping) {
        LOG_DEBUG << "recv a ping";
    }
}

void WebSocketTest::handleConnectionClosed(const WebSocketConnectionPtr &) {
    LOG_DEBUG << "websocket closed!";
}

void WebSocketTest::handleNewConnection(const HttpRequestPtr &,
                                        const WebSocketConnectionPtr &conn) {
    LOG_DEBUG << "new websocket connection!";
    conn->send("haha!!!");
}


int main(int argc, char *argv[]) {

    std::string host("0.0.0.0");
    int port(8848);
    app()
    .setLogLevel(trantor::Logger::kDebug)
    .addListener(host, port);

    auto wsPtr = WebSocketClient::newWebSocketClient(host, port);
    auto req = HttpRequest::newHttpRequest();
    req->setPath("/chat");
    wsPtr->setMessageHandler([](const std::string &message,
                                           const WebSocketClientPtr &wsPtr,
                                           const WebSocketMessageType &type) {
        std::cout << "new message:" << message << std::endl;
        if (type == WebSocketMessageType::Pong) {
            std::cout << "recv a pong" << std::endl;
        }
    });
    wsPtr->setConnectionClosedHandler([](const WebSocketClientPtr &wsPtr) {
        std::cout << "ws closed!" << std::endl;
    });
    wsPtr->connectToServer(req,
                           [](ReqResult r,
                                         const HttpResponsePtr &resp,
                                         const WebSocketClientPtr &wsPtr) {
                               if (r == ReqResult::Ok) {
                                   std::cout << "ws connected!" << std::endl;
                                   wsPtr->getConnection()->setPingMessage("",
                                                                          2s);
                                   wsPtr->getConnection()->send("hello!");
                               } else {
                                   std::cout << "ws failed!" << std::endl;
                               }
                           });
    app().run();
}

Output:

ws failed!

But with:

<!DOCTYPE html>
<pre id="log"></pre>
<script>
  // helper function: log message to screen
  function log(msg) {
    document.getElementById('log').textContent += msg + '\n';
  }

  // setup websocket with callbacks
  var ws = new WebSocket("ws://0.0.0.0:8848/chat");
  ws.onopen = function() {
    log('CONNECT');
    ws.send("hello!!!");
  };
  ws.onclose = function() {
    log('DISCONNECT');
  };
  ws.onmessage = function(event) {
    log('MESSAGE: ' + event.data);
    ws.send(event.data);
    ws.send(event.data);
  };
</script>

Works totaly fine;

CONNECT
MESSAGE: haha!!!

Please explain this behavior.

Regards.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 22 (12 by maintainers)

Most upvoted comments

If you really want create the controller by yourself. Set the second template parameter to false, and register it manually into the framework.

auto wsCtlPtr=std::make_shared<WebSocketTest>();
app().registerController(wsCtlPtr);

You don’t need to call the initPathRouting method.

Drogon automatically create WebSocketTest instance for application. the wst is not the one created by drogon and it’s not working at all. Please feel free to ask questions here.