
本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身。
文章结尾有最新热度的文章,感兴趣的可以去看看。
文章有点长(4755字阅读时长:10分),期望您能坚持看完,并有所收获
本教程将介绍如何使用功能强大的C++编程语言,编写你的首个WebSocket客户端程序,本教程将引导你顺畅地完成整个流程。

入门准备
第一步是在TraderMade注册一个账号,并获取一个可免费试用两周的API密钥。这个密钥将是我们获取实时数据的“关键所在”。获取之后,我们会用这个密钥来对我们的请求进行认证。深入研究一下“实时外汇API文档”,以便更好地了解可用的数据。
让我们通过一个实际的示例来阐述整个过程,我们将把它分解为几个易于操作的步骤:
设置编程环境
在Linux环境中使用C++会更加简便。如果使用的是Windows系统,可以通过虚拟机安装Ubuntu系统。
对于初次接触C++的人来说,我们要确保安装了用于运行C++程序的GCC编译器。
sudo apt update
要是你还没有设置密码或者忘记了密码,可以使用以下命令来重置密码:
sudo passwd
在系统更新完成后,通过执行以下命令来安装编译所需的重要工具:
sudo apt install build-essential
若要查看正在使用的GCC版本,可使用以下命令:
gcc --version
现在我们已经完成了C++编译器的设置,接下来导入运行程序所需的库。
git clone
cd websocketpp
这将从其GitHub仓库下载WebSocket++库。我们还需要另外两个库——Boost库和SSL库,使用以下命令进行安装:
git clone
cd websocketpp
编写代码
首先导入运行程序所需的库:
#include
#include
#include
接下来,我们将使用typedef定义别名,以便在后续代码中使用。websocketpp是WebSocket++库的命名空间。代码的第一行定义了一个复杂类型,它代表了支持Asio(一个用于异步I/O操作的库)和TLS(传输层安全)的WebSocket客户端。
在第二行中,shared_ptr是WebSocket++库中的智能指针,用于管理对象的内存。shared_ptr将要管理的对象类型在<符号后面定义,context_ptr是一个别名,它有助于简化使用第二行中定义的较长类型,这样代码更易于阅读,语法也更简洁。typedef websocketpp::client
typedef websocketpp::lib::shared_ptr
下面的代码现在应该更容易理解了,在前两行中,_1和_2分别是WebSocket++函数对象和回调函数所接收的第一个和第二个参数。第三行定义了bind函数,它可用于创建带有占位符的函数对象。
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
既然我们已经为处理WebSocket事件的回调函数定义了占位符和bind,接下来就为建立连接后可能遇到的每个WebSocket事件定义相应的函数。
我们首先定义on_open回调函数,当WebSocket连接成功时会调用该函数。它接收两个参数:已打开的连接句柄(hdl)以及指向WebSocket客户端(client* c)的指针。
代码中的第二行是一个输出语句,后面跟着用于错误处理的错误码以及一个连接指针(connection_ptr)。if语句用于检查在获取连接指针时是否出现错误。一旦连接没有错误,我们就传递一个字符串形式的有效载荷,并通过WebSocket连接将该载荷作为文本发送出去。
void on_open(websocketpp::connection_hdl hdl, client* c) {
std::cout <<"WebSocket connection opened!"<< std::endl;
websocketpp::lib::error_code ec;
client::connection_ptr con = c->get_con_from_hdl(hdl, ec);
if(ec){
std::cout <<"Failed to get connection pointer: "<< ec.message()<< std::endl;
return;
}
std::string payload ="{\"userKey\":\"API_KEY\", \"symbol\":\"EURUSD,GBPUSD\"}";
c->send(con, payload, websocketpp::frame::opcode::text);
}
理解了on_open回调函数后,下面的代码理解起来就相当容易了。on_message回调函数同样接收两个参数,但第二个参数是message_ptr msg,它表示接收到的外汇数据,我们会在on_message函数内部将其输出。
on_fail和on_close回调函数不需要过多解释,现在我们来看下一部分代码。
void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
std::cout << "Received message: " << msg->get_payload() << std::endl;
}
void on_fail(websocketpp::connection_hdl hdl) {
std::cout << "WebSocket connection failed!" << std::endl;
}
void on_close(websocketpp::connection_hdl hdl) {
std::cout << "WebSocket connection closed!" << std::endl;
以下函数负责创建并配置WebSocket客户端中用于安全通信的SSL上下文。我们暂不深入探讨该函数的细节,而是直接进入将所有内容整合在一起的main函数。
context_ptr on_tls_init(const char * hostname, websocketpp::connection_hdl) {
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
try{
ctx->set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3 |
boost::asio::ssl::context::single_dh_use);
ctx->set_verify_mode(boost::asio::ssl::verify_none);
}catch(std::exception& e){
std::cout <<"TLS Initialization Error: "<< e.what()<< std::endl;
}
return ctx;
}
在main函数中,我们首先定义客户端,然后定义用于连接外汇WebSocket并获取亚秒级数据的URL。
int main(int argc, char* argv[]) {
client c;
std::string hostname = "marketdata.tradermade.com/feedadv";
std::string uri = "wss://" + hostname;
}
我们在main函数内部设置一个try块来捕获任何异常。
int main(int argc, char* argv[]) {
....
try{
}catch(websocketpp::exception const& e){
std::cout <<"WebSocket Exception: "<< e.what()<< std::endl;
}
}
在try块内部,我们首先为WebSocket++客户端设置配置,然后初始化Asio以进行异步操作。接着,我们设置消息和事件处理程序,包括设置TLS(传输层安全)初始化处理程序。然后声明一个错误对象ec,并在获取连接时检查是否有错误。最后,我们使用之前创建的连接创建一个连接(c.connect(con)),并通过c.run()启动WebSocket事件循环来处理异步事件。
try {
// Configure WebSocket++ client
c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
c.set_error_channels(websocketpp::log::elevel::all);
c.init_asio();
// Set message, TLS initialization, open, fail, and close handlers
c.set_message_handler(&on_message);
c.set_tls_init_handler(bind(&on_tls_init, hostname.c_str(),::_1));
c.set_open_handler(bind(&on_open,::_1,&c));
c.set_fail_handler(bind(&on_fail,::_1));
c.set_close_handler(bind(&on_close,::_1));
// Enable detailed error logging
c.set_error_channels(websocketpp::log::elevel::all);
websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
if(ec){
std::cout <<"Could not create connection because: "<< ec.message()<< std::endl;
return0;
}
// Create a connection to the specified url
c.connect(con);
c.run();
}catch(websocketpp::exception const& e){
std::cout <<"WebSocket Exception: "<< e.what()<< std::endl;
}
完成所有代码编写后,将代码保存到一个文件中,命名为FX_WebSocket.cpp(你也可以按自己的意愿命名),然后使用以下命令编译程序:
g++ -o ./streaming_forex FX_WebSocket.cpp -lssl -lcrypto -pthread
现在,你的程序应该已经编译到streaming_forex文件中了。使用以下命令运行该文件:
./streaming_forex
瞧!现在你应该能看到与我们订阅的外汇数据建立的WebSocket连接了。别忘了在on_open函数发送有效载荷时替换你自己的API密钥。
Received message:Connected
Received message:{"symbol":"GBPUSD","ts":"1708403061263","bid":1.25867,"ask":1.25871,"mid":1.25869}
Received message:{"symbol":"GBPUSD","ts":"1708403070164","bid":1.25867,"ask":1.2587,"mid":1.258685}
Received message:{"symbol":"GBPUSD","ts":"1708403070951","bid":1.25866,"ask":1.2587,"mid":1.25868}
Received message:{"symbol":"GBPUSD","ts":"1708403071022","bid":1.25866,"ask":1.25871,"mid":1.258685}
Received message:{"symbol":"GBPUSD","ts":"1708403071213","bid":1.25866,"ask":1.2587,"mid":1.25868}
Received message:{"symbol":"GBPUSD","ts":"1708403071400","bid":1.25866,"ask":1.25869,"mid":1.258675}
Received message:{"symbol":"EURUSD","ts":"1708403071512","bid":1.07687,"ask":1.07691,"mid":1.07689}
Received message:{"symbol":"EURUSD","ts":"1708403071524","bid":1.07687,"ask":1.0769,"mid":1.076885}
Received message:{"symbol":"GBPUSD","ts":"1708403072138","bid":1.25866,"ask":1.2587,"mid":1.25868}
Received message:{"symbol":"GBPUSD","ts":"1708403074548","bid":1.25866,"ask":1.25869,"mid":1.258675}
Received message:{"symbol":"GBPUSD","ts":"1708403074618","bid":1.25866,"ask":1.2587,"mid":1.25868}
Received message:{"symbol":"GBPUSD","ts":"1708403074921","bid":1.25866,"ask":1.25869,"mid":1.258675}
Received message:{"symbol":"GBPUSD","ts":"1708403075348","bid":1.25866,"ask":1.2587,"mid":1.25868}
Received message:{"symbol":"GBPUSD","ts":"1708403077083","bid":1.25866,"ask":1.25869,"mid":1.258675}
恭喜!你刚刚使用C++和WebSocket++构建了一个实时外汇数据获取器。你可以根据自己的特定需求随意探索和修改代码,尽情享受触手可及的实时金融数据世界吧。
完整代码
以下是完整代码:
#include
#include
#include
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
void on_open(websocketpp::connection_hdl hdl, client* c) {
std::cout <<"WebSocket connection opened!"<< std::endl;
websocketpp::lib::error_code ec;
client::connection_ptr con = c->get_con_from_hdl(hdl, ec);
if(ec){
std::cout <<"Failed to get connection pointer: "<< ec.message()<< std::endl;
return;
}
std::string payload ="{\"userKey\":\"API_KEY\", \"symbol\":\"EURUSD,GBPUSD\"}";
c->send(con, payload, websocketpp::frame::opcode::text);
}
void on_message(websocketpp::connection_hdl, client::message_ptr msg) {
std::cout <<"Received message: "<< msg->get_payload()<< std::endl;
}
void on_fail(websocketpp::connection_hdl hdl) {
std::cout <<"WebSocket connection failed!"<< std::endl;
}
void on_close(websocketpp::connection_hdl hdl) {
std::cout <<"WebSocket connection closed!"<< std::endl;
}
context_ptr on_tls_init(const char * hostname, websocketpp::connection_hdl) {
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);
try{
ctx->set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3 |
boost::asio::ssl::context::single_dh_use);
}catch(std::exception& e){
std::cout <<"TLS Initialization Error: "<< e.what()<< std::endl;
}
return ctx;
}
int main(int argc, char* argv[]) {
client c;
std::string hostname ="marketdata.tradermade.com/feedadv";
std::string uri ="wss://"+ hostname;
try{
c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
c.set_error_channels(websocketpp::log::elevel::all);
c.init_asio();
c.set_message_handler(&on_message);
c.set_tls_init_handler(bind(&on_tls_init, hostname.c_str(),::_1));
c.set_open_handler(bind(&on_open,::_1,&c));
c.set_fail_handler(bind(&on_fail,::_1));
c.set_close_handler(bind(&on_close,::_1));
c.set_error_channels(websocketpp::log::elevel::all);// Enable detailed error logging
websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
if(ec){
std::cout <<"Could not create connection because: "<< ec.message()<< std::endl;
return0;
}
c.connect(con);
c.run();
}catch(websocketpp::exception const& e){
std::cout <<"WebSocket Exception: "<< e.what()<< std::endl;
}
}
展望未来
TraderMade的实时流 API 是一个易于使用且直观的资源,有助于打造数字化解决方案并提取有价值的见解。你可以随意在 C++ 中利用它的潜力来创建出色的应用程序,别忘了和我们分享你的成果哦。
以上就是我的分享。这些分析皆源自我的个人经验,希望上面分享的这些东西对大家有帮助,感谢大家!

最新热门文章推荐:
用纯C++实现神经网络:不依赖Python和PyTorch,260行代码训练手写数字分类器准确率高达99%,你敢信?
中国人眼中的Yoshua Bengio:将人工智能安全理念带入现实应用并影响全球政策制定?
为何开发者:正在抛弃PostgreSQL、MySQL 和 MongoDB
马斯克等大佬质疑:OpenAI引领的人工智能发展道路,究竟是进步还是灾难的前奏?
国外程序员分享:C++在底层性能和实时线程处理方面碾压Rust
不要盲目刷题(LeetCode):先学会这 15 种模式,做题变得简单
还在为代码部署发愁?学会这25个Docker命令,让一切变得简单高效!
参考文献:
《图片素材来源网络》