基于websocketpp库的websocket服务器例程

使用websocketpp,需要安装boost。

解压 boost_1_73_0.tar.gz

tar -zvfx boost_1_73_0.tar.gz

运行bootstrap.sh后,生成b2,直接运行b2;如果需要移植到ARM平台,则需要在project-config.jam文件将using gcc修改如下:

using gcc : : arm-linux-gnueabihf-gcc;

生成的库文件在stage目录中。

下面是websocket服务器例程,该服务器功能用于推送数据到客户端,对连接到服务器的客户端,服务器定时推送数据到客户端。这里简单实现了两个推送地址,分别为ws://localhost:9000/push/helloworld和ws://localhost:9000/current/status。

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

#include <set>
#include <string>
#include <iostream>

/*
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>*/
#include <websocketpp/common/thread.hpp>

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;

using websocketpp::lib::thread;
using websocketpp::lib::mutex;
using websocketpp::lib::lock_guard;
using websocketpp::lib::unique_lock;
using websocketpp::lib::condition_variable;

enum action_type {
    SUBSCRIBE,
    UNSUBSCRIBE,
    MESSAGE
};

typedef server::message_ptr message_ptr;

struct action {
    action(action_type t, std::string s, connection_hdl h) : type(t), struri(s), hdl(h) {}
    action(action_type t, std::string s, connection_hdl h, server::message_ptr m)
      : type(t), struri(s), hdl(h), msg(m) {}

    action_type type;
    std::string struri;
    websocketpp::connection_hdl hdl;
    server::message_ptr msg;
};

/**************************************************************************************************/ 
class broadcast_server {
public:
    broadcast_server() {
        // Initialize Asio Transport
        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));
	    //接收websocket数据回调函数
        m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
    }

    void run(uint16_t port) {
        m_server.listen(port);
        m_server.start_accept();

        set_helloworld_timer();
	    set_status_timer();

        try {
            m_server.run();
        } catch (const std::exception & e) {
            std::cout << e.what() << std::endl;
        }
    }


    void set_status_timer() {
        m_sensor_timer = m_server.set_timer(
            10000,
            websocketpp::lib::bind(
                &broadcast_server::robot_status,
                this,
                websocketpp::lib::placeholders::_1
            )
        );
    }

    void robot_status(websocketpp::lib::error_code const & ec) {
        if (ec) {
            m_server.get_alog().write(websocketpp::log::alevel::app, "Timer Error: "+ec.message());
            return;
        }
        
        std::stringstream val;
	    std::string data = struct_robot_status();
        val << "current status \r\n";
        con_list::iterator it;
        for (it = m_status_connections.begin(); it != m_status_connections.end(); ++it) {
	    m_server.send(*it,val.str(),websocketpp::frame::opcode::text);
        }       
	    set_status_timer();
    }
    /************************************************************************/
    void set_helloworld_timer() {
        m_helloworld_timer= m_server.set_timer(
            2000,
            websocketpp::lib::bind(
                &broadcast_server::sensor_value,
                this,
                websocketpp::lib::placeholders::_1
            )
        );
    }

    void helloworld_routine(websocketpp::lib::error_code const & ec) {
        if (ec) {
            m_server.get_alog().write(websocketpp::log::alevel::app, "Timer Error:                 "+ec.message());
            return ;
        }
        
        std::stringstream val;
	    std::string data = struct_sensor_data();
        val << "hello world \r\n";
        con_list::iterator it;
        for (it = m_sensor_connections.begin(); it != m_sensor_connections.end(); ++it) {
	        m_server.send(*it, val.str(), websocketpp::frame::opcode::text);
        } 
        set_helloworld_timer();
    }
    /************************************************************************/
    void on_open(connection_hdl hdl) {
        {
            lock_guard<mutex> guard(m_action_lock);
	    server::connection_ptr con = m_server.get_con_from_hdl(hdl);	
	    websocketpp::http::parser::request rt = con->get_request();
            m_actions.push(action(SUBSCRIBE, rt.get_uri(), hdl));
        }
        m_action_cond.notify_one();
    }

    void on_close(connection_hdl hdl) {
        {
            lock_guard<mutex> guard(m_action_lock);
	    server::connection_ptr con = m_server.get_con_from_hdl(hdl);	
	    websocketpp::http::parser::request rt = con->get_request();
            m_actions.push(action(UNSUBSCRIBE, rt.get_uri(), hdl));
        }
        m_action_cond.notify_one();
    }

    void on_message(connection_hdl hdl, server::message_ptr msg) {
        {
            lock_guard<mutex> guard(m_action_lock);
	    server::connection_ptr con = m_server.get_con_from_hdl(hdl);	
	    websocketpp::http::parser::request rt = con->get_request();
            m_actions.push(action(MESSAGE, rt.get_uri(), hdl, msg));
        }
        m_action_cond.notify_one();
    }

    void process_messages() {
        while(1) {
            unique_lock<mutex> lock(m_action_lock);

            while(m_actions.empty()) {
                m_action_cond.wait(lock);
            }

            action a = m_actions.front();
            m_actions.pop();

            lock.unlock();

    	    if(0 == a.struri.compare(std::string("/push/helloworld"))) {
            	if (a.type == SUBSCRIBE) {
                	lock_guard<mutex> guard(m_connection_lock);
                	m_helloworld_connections.insert(a.hdl);
            	} else if (a.type == UNSUBSCRIBE) {
                	lock_guard<mutex> guard(m_connection_lock);
                	m_helloworld_connections.erase(a.hdl);
            	} else if (a.type == MESSAGE) {
                	lock_guard<mutex> guard(m_connection_lock);
            	} else {
                	// undefined.
            	}
    	    } else if(0 == a.struri.compare(std::string("/current/status"))) {
            	if (a.type == SUBSCRIBE) {
                	lock_guard<mutex> guard(m_connection_lock);
                	m_status_connections.insert(a.hdl);
            	} else if (a.type == UNSUBSCRIBE) {
                	lock_guard<mutex> guard(m_connection_lock);
                	m_status_connections.erase(a.hdl);
            	} else if (a.type == MESSAGE) {
                	lock_guard<mutex> guard(m_connection_lock);
            	} else {
                	// undefined.
            	}
	        } else {

	        }
        }
    }

private:
    typedef std::set<connection_hdl,std::owner_less<connection_hdl> > con_list;

    server m_server;
    server::timer_ptr m_helloworld_timer;
    server::timer_ptr m_status_timer;
    con_list m_helloworld_connections;
    con_list m_status_connections;
    std::queue<action> m_actions;

    mutex m_action_lock;
    mutex m_connection_lock;
    condition_variable m_action_cond;
};

int main(int argc, char *argv[])
{
    try {
	broadcast_server server_instance;
	thread t(bind(&broadcast_server::process_messages,&server_instance));
	server_instance.run(9000);
	t.join();
    } catch (websocketpp::exception const & e) {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

编译命令:

g++ -std=gnu++14 -o server websocket_server.cpp -I/DIR/websocketpp -I/DIR/boost/include -L/DIR/boost/lib -lboost_system -lboost_chrono -lpthread

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值