0

I am writing a plugin for the Elgato Stream Deck. The Stream Deck uses a web socket for communication with plugins. I am trying to write my plugin as a console app in C#. The "compiled plugin" example provided by Elgato is broken (this GitHub issue points to one problem, and there appear to be more) and does not appear to run - so I have been digging through the code to make sense of it and translate it to C# without using Visual Studio debugging. I did find this, however (link to code file on GitHub):

void ESDConnectionManager::Run()
{
    try
    {
        // Create the endpoint
        mWebsocket.clear_access_channels(websocketpp::log::alevel::all);
        mWebsocket.clear_error_channels(websocketpp::log::elevel::all);
    
        // Initialize ASIO
        mWebsocket.init_asio();
        
        // Register our message handler
        mWebsocket.set_open_handler(websocketpp::lib::bind(&ESDConnectionManager::OnOpen, this, &mWebsocket, websocketpp::lib::placeholders::_1));
        mWebsocket.set_fail_handler(websocketpp::lib::bind(&ESDConnectionManager::OnFail, this, &mWebsocket, websocketpp::lib::placeholders::_1));
        mWebsocket.set_close_handler(websocketpp::lib::bind(&ESDConnectionManager::OnClose, this, &mWebsocket, websocketpp::lib::placeholders::_1));
        mWebsocket.set_message_handler(websocketpp::lib::bind(&ESDConnectionManager::OnMessage, this, websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2));
    
        websocketpp::lib::error_code ec;
        std::string uri = "ws://127.0.0.1:" + std::to_string(mPort);
        WebsocketClient::connection_ptr connection = mWebsocket.get_connection(uri, ec);
        if (ec)
        {
            DebugPrint("Connect initialization error: %s\n", ec.message().c_str());
            return;
        }
    
        mConnectionHandle = connection->get_handle();
    
        // Note that connect here only requests a connection. No network messages are
        // exchanged until the event loop starts running in the next line.
        mWebsocket.connect(connection);
    
        // Start the ASIO io_service run loop
        // this will cause a single connection to be made to the server. mWebsocket.run()
        // will exit when this connection is closed.
        mWebsocket.run();
    }
    catch (websocketpp::exception const & e)
    {
        // Prevent an unused variable warning in release builds
        (void)e;
        DebugPrint("Websocket threw an exception: %s\n", e.what());
    }
}

This appears to be using some library called boost.asio? The closest thing I can find in C# is the MessageWebSocket from Windows.Networking.Sockets (documentation here) but this appears to be only for Windows RT?

How do I create something analogous to this in a .NET console app? I have found references to System.Net.WebSockets.ClientWebSocket (documentation here), which appears to be the class I need, but I am not sure.

I have found a few samples (such as this one, and this one - both of which use yet another socket class, Socket) that show how to use Sockets in general, but they do not seem event-driven. They seem to send, and then immediately receive data. I want a web socket that calls local methods (akin to event handlers) when events/data are received by the socket. I believe this is what is going on in the sample C++ code above (specifically Open, Fail, Close, and Message). My understanding is that I need to do some work ("register" with the Stream Deck) on the web socket "Open" event, and then handle the web socket "Message" event and parse out what event the Stream Deck is reporting happened.

1 Answers1

0

If you scroll down some lines in your example https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket?view=net-7.0 you will find a example called: Asyncronous Mode that handles sending and receiving separately.

Send part

   int bytesSent = 0;
    while (bytesSent < requestBytes.Length)
    {
        bytesSent += await socket.SendAsync(requestBytes.AsMemory(bytesSent), SocketFlags.None);
    }

If you do not want the program to lock up, the easiest way would be to start a thread for listening maybe?

Lasersköld
  • 2,028
  • 14
  • 20