C++编写的WebSocket服务端客户端实现示例代码
时间:2022-01-26 10:14:34|栏目:C代码|点击: 次
使用过标准的libwebsockets服务端库测试过,主要是短小精悍,相对于libwebsockets不需要依赖zlib和openssl 以及其他库,直接make就可以使用了,linux跟windows都可以使用。
测试用例:
#include "easywsclient.hpp" #include <assert.h> #include <stdio.h> #include <string> using easywsclient::WebSocket; static WebSocket::pointer ws = NULL; void handle_message(const std::string & message) { printf(">>> %s\n", message.c_str()); if (message == "world") { ws->close(); } } int main() { ws = WebSocket::from_url("ws://localhost:8126/foo"); assert(ws);//判断ws对象是否为空null ws->send("goodbye"); ws->send("hello"); //如果你需要多线程,可以在一个thread 维护该ws的连接重连机制 while (ws->getReadyState() != WebSocket::CLOSED) //判断ws是否正常连接 { ws->poll();//这个必须要调用,否则不能发送,发送跟接收都是异步的,都是在这个poll函数里监测处理的 ws->dispatch(handle_message); } delete ws; return 0; }
//线程thread 维护重连连接 void run() { bool conn = FLASE; ws = WebSocket::from_url("ws://localhost:8126/foo"); //如果你需要多线程,可以在一个thread 维护该ws的连接重连机制 while (1) //判断ws是否正常连接 { if(ws != NULL) { ws->poll(0);//这个必须要调用,否则不能发送,发送跟接收都是异步的,都是在这个poll函数里监测处 理的 ws->dispatch(handle_message); if(ws->getReadyState() == WebSocket::CLOSED) { //ws连接断开 重连 delete ws; ws = NULL; ws = WebSocket::from_url("ws://localhost:8126/foo"); } else if(wss->getReadyState()== WebSocket::OPEN) { //ws连接ok // ws->send("goodbye"); ws->send("hello"); } } else { ws = WebSocket::from_url("ws://localhost:8126/foo"); sleep(1); } usleep(100); } if(ws!=NULL) delete ws; }
有细心的朋友发现在发送中文GBK 的时候与服务端会断开
//GBK -> UTF-8 //遇到发送的字符串里有中文的话需要send 前进行转换一下, //这个是网友提供的在windows下的转换函数 std::string Server_Stream::GBKToUTF8(const std::string& strGBK) { std::string strOutUTF8 = ""; WCHAR * str1; int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0); str1 = new WCHAR[n]; MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n); n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL); char * str2 = new char[n]; WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL); strOutUTF8 = str2; delete[]str1; str1 = NULL; delete[]str2; str2 = NULL; return strOutUTF8; }
下面是C++实现的WebSocket客户端,写好后这里记一下,免得以后忘记。
本示例共有三个文件组成,依赖Websocket++第三方库
其中main.cpp是使用示例
#include <iostream> #include <string> #include <sstream> #include "websocket_endpoint.h" int main(int argc, char **argv) { bool done = false; std::string input; kagula::websocket_endpoint endpoint; endpoint.connect("ws://localhost:9002"); while (!done) { std::cout << "Enter Command: "; std::getline(std::cin, input); if (input == "quit") { done = true; } else if (input.substr(0, 4) == "send") { std::stringstream ss(input); std::string cmd; std::string message; ss >> cmd; std::getline(ss, message); endpoint.send(message); } else if (input.substr(0, 4) == "show") { endpoint.show(); } else { std::cout << "> Unrecognized Command" << std::endl; } } endpoint.close(); return 0; }
其它两个文件是封装
websocket_endpoint.h文件清单
#ifndef _WEBSOCKET_ENDPOINT_ #define _WEBSOCKET_ENDPOINT_ #include <string> /* Title: Web Socket Client Author: kagula Date: 2016-11-21 Dependencies: Websocket++、Boost::ASIO Test Environment: VS2013 Update5, WebSocket++ 0.70, Boost 1.61 Description: [1]Support connect a web socket server. [2]If server is crash, client will not follow crash. */ namespace kagula { class websocket_endpoint { public: websocket_endpoint(); ~websocket_endpoint(); int connect(std::string const & uri); void close(); void send(std::string message); void show(); }; } #endif
websocket_endpoint.cpp文件清单
#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 "websocket_endpoint.h" typedef websocketpp::client<websocketpp::config::asio_client> ws_client; namespace kagula { class connection_metadata { public: typedef websocketpp::lib::shared_ptr<connection_metadata> ptr; connection_metadata(websocketpp::connection_hdl hdl, std::string uri) : m_hdl(hdl) , m_status("Connecting") , m_uri(uri) , m_server("N/A") {} void on_open(ws_client *client, websocketpp::connection_hdl hdl) { m_status = "Open"; ws_client::connection_ptr con = client->get_con_from_hdl(hdl); m_server = con->get_response_header("Server"); } // if connection failed, the function will be invoke. void on_fail(ws_client *client, websocketpp::connection_hdl hdl) { m_status = "Failed"; ws_client::connection_ptr con = client->get_con_from_hdl(hdl); m_server = con->get_response_header("Server"); m_error_reason = con->get_ec().message(); } void on_close(ws_client *client, websocketpp::connection_hdl hdl) { m_status = "Closed"; ws_client::connection_ptr con = client->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(); m_error_reason = s.str(); } void on_message(websocketpp::connection_hdl, ws_client::message_ptr msg) { if (msg->get_opcode() == websocketpp::frame::opcode::text) { m_messages.push_back("<< " + msg->get_payload()); } else { m_messages.push_back("<< " + websocketpp::utility::to_hex(msg->get_payload())); } } websocketpp::connection_hdl get_hdl() const { return m_hdl; } std::string get_status() const { return m_status; } std::string get_uri() const { return m_uri; } void record_sent_message(std::string message) { m_messages.push_back(">> " + message); } friend std::ostream & operator<< (std::ostream & out, connection_metadata const & data); private: websocketpp::connection_hdl m_hdl; std::string m_status; std::string m_uri; std::string m_server; std::string m_error_reason; std::vector<std::string> m_messages; }; std::ostream & operator<< (std::ostream & out, connection_metadata const & data) { out << "> URI: " << data.m_uri << "\n" << "> Status: " << data.m_status << "\n" << "> Remote Server: " << (data.m_server.empty() ? "None Specified" : data.m_server) << "\n" << "> Error/close reason: " << (data.m_error_reason.empty() ? "N/A" : data.m_error_reason) << "\n"; out << "> Messages Processed: (" << data.m_messages.size() << ") \n"; std::vector<std::string>::const_iterator it; for (it = data.m_messages.begin(); it != data.m_messages.end(); ++it) { out << *it << "\n"; } return out; } ws_client g_wsEndPoint; connection_metadata::ptr g_wsClientConnection; websocketpp::lib::shared_ptr<websocketpp::lib::thread> g_threadWS; websocket_endpoint::websocket_endpoint(){ g_wsEndPoint.clear_access_channels(websocketpp::log::alevel::all); g_wsEndPoint.clear_error_channels(websocketpp::log::elevel::all); g_wsEndPoint.init_asio(); g_wsEndPoint.start_perpetual(); g_threadWS = websocketpp::lib::make_shared<websocketpp::lib::thread>(&ws_client::run, &g_wsEndPoint); } websocket_endpoint::~websocket_endpoint() { g_wsEndPoint.stop_perpetual(); if (g_wsClientConnection->get_status() == "Open") { // Only close open connections websocketpp::lib::error_code ec; g_wsEndPoint.close(g_wsClientConnection->get_hdl(), websocketpp::close::status::going_away, "", ec); if (ec) { std::cout << "> Error closing ws connection " << g_wsClientConnection->get_uri() << " :" << ec.message() << std::endl; } } g_threadWS->join(); } int websocket_endpoint::connect(std::string const & uri) { websocketpp::lib::error_code ec; ws_client::connection_ptr pConnection = g_wsEndPoint.get_connection(uri, ec); if (ec) { std::cout << "> Connect initialization error: " << ec.message() << std::endl; return -1; } g_wsClientConnection = websocketpp::lib::make_shared<connection_metadata>(pConnection->get_handle(), uri); pConnection->set_open_handler(websocketpp::lib::bind( &connection_metadata::on_open, g_wsClientConnection, &g_wsEndPoint, websocketpp::lib::placeholders::_1 )); pConnection->set_fail_handler(websocketpp::lib::bind( &connection_metadata::on_fail, g_wsClientConnection, &g_wsEndPoint, websocketpp::lib::placeholders::_1 )); pConnection->set_close_handler(websocketpp::lib::bind( &connection_metadata::on_close, g_wsClientConnection, &g_wsEndPoint, websocketpp::lib::placeholders::_1 )); pConnection->set_message_handler(websocketpp::lib::bind( &connection_metadata::on_message, g_wsClientConnection, websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2 )); g_wsEndPoint.connect(pConnection); return 0; } void close(websocketpp::close::status::value code, std::string reason) { websocketpp::lib::error_code ec; g_wsEndPoint.close(g_wsClientConnection->get_hdl(), code, reason, ec); if (ec) { std::cout << "> Error initiating close: " << ec.message() << std::endl; } } void websocket_endpoint::close() { if (g_wsClientConnection->get_status()=="Open") { int close_code = websocketpp::close::status::normal; kagula::close(close_code, ""); } } void websocket_endpoint::send(std::string message) { websocketpp::lib::error_code ec; g_wsEndPoint.send(g_wsClientConnection->get_hdl(), message, websocketpp::frame::opcode::text, ec); if (ec) { std::cout << "> Error sending message: " << ec.message() << std::endl; return; } g_wsClientConnection->record_sent_message(message); } void websocket_endpoint::show() { std::cout << * g_wsClientConnection << std::endl; } }
栏 目:C代码
下一篇:C语言预处理详解
本文标题:C++编写的WebSocket服务端客户端实现示例代码
本文地址:http://www.codeinn.net/misctech/191420.html