zaphoyd / websocketpp

C++ websocket client/server library
http://www.zaphoyd.com/websocketpp
Other
7.05k stars 1.97k forks source link

Websocket server initiated data + client initiated data sample code. #618

Open hiharsh opened 7 years ago

hiharsh commented 7 years ago

Hi, I am fairly new to this web programming and would appreciate your help. I would like o achieve following 1) Start a websocket server on C++ 2_ Listen for messages from client 3)send response for messages based on some processing in my custom code. SEND SERVER INITIATED text message/string to client when something changes on my custom code. For # 1 to 3 I can use the echo server for 1 to 1 message handling (but that would be blocking to since I will be filling the response to the send string after I have processed the request from client).

Any example code?

dummy test class below.

test.cpp
class test
{
public:
void processDataFromClient(const string & data);//this needs to get filled by websocket read method? how?
void pushDataToClient(const string & data);

};
test::pushDataToClient(const string & data)
{
async_write(socketId, text) // how do I call this from my test.cpp?
}

test::void processDataFromClient(const string & data)
{
//do some computation based on the text received
//turn on the light
//once Light is on for a minute call
pushDataToClient( lighton) ;
}

//web_socket_server.cpp
main
{
//open a webSocket
//listen for messages from client //notify test class
//send messages to client once write is called from test class ? //do we need a thread for this ? how to acheive this?
}
hiharsh commented 7 years ago

I adapted the simple_broadcast_server code as shown below to send server initiated data to all client(s). FYI. I have a baseStation class which pushes the message/string to queue upon invoking BaseStation->start() method. I am not expert on C++, If someone can review and pass the comments to improve it that would be really appreciated. Also, please let me know if there is any error checking needs to be incorporated if yes, any example. Finally, I am not 100% confident about while(1) loop here , is there a better way to reduce CPU utilization? and protect the bytequeue while operating on it? i.e mutex or any mechanism. It would be good if someone can post example/code snippet associated with above mentioned points.

#include <set>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include "./src/agent/baseStation.h"

using namespace std;
typedef websocketpp::server<websocketpp::config::asio> server;

using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;

class broadcast_server {
public:
    broadcast_server() {
        m_server.init_asio();

        m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
        m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
        m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
    }

    void on_open(connection_hdl hdl) {
        m_connections.insert(hdl);
    }

    void on_close(connection_hdl hdl) {
        m_connections.erase(hdl);
    }

    void on_message(connection_hdl hdl, server::message_ptr msg) {
        //for (auto it : m_connections) {
        //  m_server.send(it,msg);
        //write a parser to parse the messages and send it to respective modules 
        BaseStation * baseStationPtr= BaseStation::getBaseStationInstance();
        baseStationPtr->start();
       }
    }

    void run(uint16_t port) {
        m_server.listen(port);
        m_server.start_accept();
        m_server.run();
    }
    void asyncWriteToClient(void)
    {
        BaseStation * BaseStationPtr= BaseStation::getBaseStationInstance();
         while(1)
         {
             while (!BaseStationPtr->byte_queue_.empty())
              {
                   string msg = BaseStationPtr->byte_queue_.front();
                   for (auto it : m_connections)
                     {
                          m_server.send(it,msg,websocketpp::frame::opcode::text);
                      }
                      // m_server.send(it,msg,websocketpp::frame::opcode::text);
                      BaseStationPtr->byte_queue_.pop();
               }
            sleep(1);
          }
       }
private:
    typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
    server m_server;
    con_list m_connections;
};

int main() {
    broadcast_server server;
    std::thread t(std::bind(&broadcast_server::asyncWriteToClient,&server));
    server.run(80);
}