Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebSocket sendFrame Delay and ReceiveTimeout Dependency - Need Help #4756

Open
The-Robin-Hood opened this issue Nov 2, 2024 · 0 comments
Open

Comments

@The-Robin-Hood
Copy link

Hi,
I'm having a problem with Poco::Net::WebSocket.sendFrame(). It takes forever (about 2 seconds) to execute in a non-blocking context. It seems that sendFrame() only works when a receive timeout happens, which makes the receiving end laggy and timeouty. I tried setting the WebSocket to non-blocking mode with ws->setBlocking(false), but that didn't help. If I set ws->setReceiveTimeout(Poco::Timespan(0, 1000)), the receive timeout keeps getting called, and sendFrame() doesn't lag at all.

What am I missing? Should I set the timeout low, catch it, and then ignore it? I'd appreciate any help or suggestions.
I've attached a sample code below.

#include <chrono>
#include <iostream>
#include <thread>

#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/WebSocket.h"

class WebSocketClient {
   private:
    Poco::Net::WebSocket* ws;
    std::thread receiveThread;
    std::atomic<bool> running{true};

   public:
    WebSocketClient(const std::string& host, uint16_t port, const std::string& path) {
        Poco::Net::Context::Ptr context = new Poco::Net::Context(
            Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE, 9, false,
            "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");

        Poco::Net::HTTPSClientSession session(host, port, context);
        session.setTimeout(Poco::Timespan(5, 0)); 
        Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path,
                                       Poco::Net::HTTPMessage::HTTP_1_1);
        Poco::Net::HTTPResponse response;

        ws = new Poco::Net::WebSocket(session, request, response);
        // ws->setReceiveTimeout(Poco::Timespan(0, 1000)); 
        receiveThread = std::thread(&WebSocketClient::receiveLoop, this);
    }

    ~WebSocketClient() {
        running = false;
        if (receiveThread.joinable()) {
            receiveThread.join();
        }
        delete ws;
    }

    bool sendMessage(const std::string& message) {
        try {
            auto start = std::chrono::steady_clock::now();

            int flags = Poco::Net::WebSocket::FRAME_TEXT;
            int sent = ws->sendFrame(message.data(), message.length(), flags);

            auto end = std::chrono::steady_clock::now();
            auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

            std::cout << "Time taken for sendFrame: " << duration.count() << " ms\n";

            return sent == message.length();
        } catch (const Poco::TimeoutException& e) {
            std::cerr << "Timeout sending message: " << e.what() << std::endl;
            return false;
        } catch (const Poco::Exception& e) {
            std::cerr << "Error sending message: " << e.what() << std::endl;
            return false;
        }
    }

   private:
    void receiveLoop() {
        const int BUFFER_SIZE = 1024;
        char buffer[BUFFER_SIZE];
        int flags = 0;

        while (running) {
            try {
                int received = ws->receiveFrame(buffer, sizeof(buffer), flags);
                if (received > 0) {
                    std::string message(buffer, received);
                    std::cout << "Received message: " << message << std::endl;
                }
            } catch (const Poco::TimeoutException&) {
                std::cerr << "Timeout receiving message\n";
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                continue;
            } catch (const Poco::Exception& e) {
                std::cerr << "Error in receive loop: " << e.what() << std::endl;
                break;
            }
        }
    }
};

int main() {
    try {
        WebSocketClient client("echo.websocket.org", 443, "/");

        while (true) {
            std::cout << "Sending message: test\n";
            client.sendMessage("test");
            std::this_thread::sleep_for(std::chrono::seconds(3));
        }
    } catch (const Poco::Exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant