websocket C++使用
websocket库安装
使用websocketpp C++库进行集成使用,针对的是C++环境编程
下载websocketpp
git clone https://github.com/zaphoyd/websocketpp.git
如果连不上github,头顶连接可以下载,我上传了一份。需要分是默认的,我决定不了。
websocketpp 编译是不会生成库文件的的,使用以下指令进行安装只是将websocketpp文件拷贝到了/usr/local/include目录下。如果你不想安装,可以将该文件夹拷贝到你的工程目录。
cd websocketpp/
mkdir build
cmake ..
make
sudo make install
安装websocketpp 依赖
sudo apt-get install libboost-all-dev
websocketpp客户端
websocketpp使用查看example文件夹,里面有各种例程。
这里贴一个修改过的,可以获取接收到的消息
#pragma once
#include "websocketpp/config/asio_no_tls_client.hpp"
#include "websocketpp/client.hpp"
#include "websocketpp/common/thread.hpp"
#include "websocketpp/common/memory.hpp"
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <sstream>
#include <queue>
//websocket 客户端实现
typedef websocketpp::client<websocketpp::config::asio_client> client;
class connection_metadata {
public:
typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;
connection_metadata(int id, websocketpp::connection_hdl hdl, std::string uri)
: id_(id)
, hdl_(hdl)
, status_("Connecting")
, uri_(uri)
, server_("N/A")
{}
void on_open(client * c, websocketpp::connection_hdl hdl) {
status_ = "Open";
client::connection_ptr con = c->get_con_from_hdl(hdl);
server_ = con->get_response_header("Server");
}
void on_fail(client * c, websocketpp::connection_hdl hdl) {
status_ = "Failed";
client::connection_ptr con = c->get_con_from_hdl(hdl);
server_ = con->get_response_header("Server");
error_reason_ = con->get_ec().message();
}
void on_close(client * c, websocketpp::connection_hdl hdl) {
status_ = "Closed";
client::connection_ptr con = c->get_con_from_hdl(hdl);
std::stringstream s;
s << "close code: " << con->get_remote_close_code() << " ("
<< websocketpp::close::status::get_string(con->get_remote_close_code())
<< "), close reason: " << con->get_remote_close_reason();
error_reason_ = s.str();
}
void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
if (msg->get_opcode() == websocketpp::frame::opcode::text) {
//messages_.push_back("<< " + msg->get_payload());
{
std::unique_lock<std::mutex> lock(message_queue_mutex_);
message_queue_.push(msg->get_payload());
}
message_queue_cv_.notify_one();
} else {
//messages_.push_back("<< " + websocketpp::utility::to_hex(msg->get_payload()));
}
}
websocketpp::connection_hdl get_hdl() const {
return hdl_;
}
int get_id() const {
return id_;
}
std::string get_status() const {
return status_;
}
void record_sent_message(std::string message) {
messages_.push_back(">> " + message);
}
bool get_message(std::string& message) {
std::unique_lock<std::mutex> lock(message_queue_mutex_);
if (message_queue_.empty()) {
return false;
}
message = message_queue_.front();
message_queue_.pop();
return true;
}
//阻塞,收到消息返回
bool get_message_blocking(std::string& message) {
std::unique_lock<std::mutex> lock(message_queue_mutex_);
message_queue_cv_.wait(lock, [this] { return !message_queue_.empty(); });
message = message_queue_.front();
message_queue_.pop();
return true;
}
friend std::ostream & operator<< (std::ostream & out, connection_metadata const & data);
private:
int id_;
websocketpp::connection_hdl hdl_;
std::string status_;
std::string uri_;
std::string server_;
std::string error_reason_;
std::vector<std::string> messages_;
std::queue<std::string> message_queue_;
std::mutex message_queue_mutex_;
std::condition_variable message_queue_cv_;
};
std::ostream & operator<< (std::ostream & out, connection_metadata const & data) {
out << "> URI: " << data.uri_ << "\n"
<< "> Status: " << data.status_ << "\n"
<< "> Remote Server: " << (data.server_.empty() ? "None Specified" : data.server_) << "\n"
<< "> Error/close reason: " << (data.error_reason_.empty() ? "N/A" : data.error_reason_) << "\n";
out << "> Messages Processed: (" << data.messages_.size() << ") \n";
std::vector<std::string>::const_iterator it;
for (it = data.messages_.begin(); it != data.messages_.end(); ++it) {
out << *it << "\n";
}
return out;
}
class WebsocketClient {
public:
WebsocketClient () : next_id_(0) {
wsc_.clear_access_channels(websocketpp::log::alevel::all);
wsc_.clear_error_channels(websocketpp::log::elevel::all);
wsc_.init_asio();
wsc_.start_perpetual();
thread_ = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &wsc_);
}
~WebsocketClient() {
wsc_.stop_perpetual();
for (con_list::const_iterator it = connection_list_.begin(); it != connection_list_.end(); ++it) {
if (it->second->get_status() != "Open") {
// Only close open connections
continue;
}
std::cout << "> Closing connection " << it->second->get_id() << std::endl;
websocketpp::lib::error_code ec;
wsc_.close(it->second->get_hdl(), websocketpp::close::status::going_away, "", ec);
if (ec) {
std::cout << "> Error closing connection " << it->second->get_id() << ": "
<< ec.message() << std::endl;
}
}
thread_->join();
}
int connect(std::string const & uri) {
websocketpp::lib::error_code ec;
client::connection_ptr con = wsc_.get_connection(uri, ec);
if (ec) {
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
return -1;
}
int new_id = next_id_++;
connection_metadata::ptr metadata_ptr = websocketpp::lib::make_shared<connection_metadata>(new_id, con->get_handle(), uri);
connection_list_[new_id] = metadata_ptr;
con->set_open_handler(websocketpp::lib::bind(
&connection_metadata::on_open,
metadata_ptr,
&wsc_,
websocketpp::lib::placeholders::_1
));
con->set_fail_handler(websocketpp::lib::bind(
&connection_metadata::on_fail,
metadata_ptr,
&wsc_,
websocketpp::lib::placeholders::_1
));
con->set_close_handler(websocketpp::lib::bind(
&connection_metadata::on_close,
metadata_ptr,
&wsc_,
websocketpp::lib::placeholders::_1
));
con->set_message_handler(websocketpp::lib::bind(
&connection_metadata::on_message,
metadata_ptr,
websocketpp::lib::placeholders::_1,
websocketpp::lib::placeholders::_2
));
wsc_.connect(con);
return new_id;
}
void close(int id, websocketpp::close::status::value code, std::string reason) {
websocketpp::lib::error_code ec;
con_list::iterator metadata_it = connection_list_.find(id);
if (metadata_it == connection_list_.end()) {
std::cout << "> No connection found with id " << id << std::endl;
return;
}
wsc_.close(metadata_it->second->get_hdl(), code, reason, ec);
if (ec) {
std::cout << "> Error initiating close: " << ec.message() << std::endl;
}
}
void send(int id, std::string message) {
websocketpp::lib::error_code ec;
con_list::iterator metadata_it = connection_list_.find(id);
if (metadata_it == connection_list_.end()) {
std::cout << "> No connection found with id " << id << std::endl;
return;
}
wsc_.send(metadata_it->second->get_hdl(), message, websocketpp::frame::opcode::text, ec);
if (ec) {
std::cout << "> Error sending message: " << ec.message() << std::endl;
return;
}
//metadata_it->second->record_sent_message(message);
}
std::string get_status(int id){
con_list::iterator metadata_it = connection_list_.find(id);
if (metadata_it == connection_list_.end()) {
std::cout << "> No connection found with id " << id << std::endl;
return "unconnect";
}
return metadata_it->second->get_status();
}
bool get_message(int id, std::string& message) {
con_list::iterator metadata_it = connection_list_.find(id);
if (metadata_it == connection_list_.end()) {
std::cout << "> No connection found with id " << id << std::endl;
return false;
}
return metadata_it->second->get_message(message);
}
bool get_message_blocking(int id, std::string& message) {
con_list::iterator metadata_it = connection_list_.find(id);
if (metadata_it == connection_list_.end()) {
std::cout << "> No connection found with id " << id << std::endl;
return false;
}
return metadata_it->second->get_message_blocking(message);
}
connection_metadata::ptr get_metadata(int id) const {
con_list::const_iterator metadata_it = connection_list_.find(id);
if (metadata_it == connection_list_.end()) {
return connection_metadata::ptr();
} else {
return metadata_it->second;
}
}
private:
typedef std::map<int,connection_metadata::ptr> con_list;
client wsc_;
websocketpp::lib::shared_ptr<websocketpp::lib::thread> thread_;
con_list connection_list_;
int next_id_;
};
集成使用
int main() {
WebsocketClient wsc;
std::string uri = "ws://localhost:9002";
int id = wsc.connect(uri);
if (id != -1) {
std::cout << "> Created connection with id " << id << std::endl;
}
std::string message;
while(1){
if (wsc.get_message(id, message)) {
std::cout << "Received : " << message << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
wsc.send(id, "message");
}
wsc.close(id,"out");
return 0;
}