【发布时间】:2019-09-02 16:35:57
【问题描述】:
我正在尝试使用 boost async_connect(...) 编写一种非常优雅的方法来处理重新连接循环。问题是,我没有办法优雅地解决以下问题:
我有一个 TCP 客户端,它应该尝试异步连接到服务器,如果由于服务器脱机或发生任何其他错误而导致连接失败,请等待给定的时间并尝试重新连接。这里有很多事情需要考虑:
- 尽可能避免使用全局变量
- 必须是异步连接
一个非常基本的客户端是这样实例化的:
tcpclient::tcpclient(std::string host, int port) : _endpoint(boost::asio::ip::address::from_string(host), port), _socket(_ios) {
logger::log_info("Initiating client ...");
}
尝试连接服务器:
void tcpclient::start() {
bool is_connected = false;
while (!is_connected) {
_socket.async_connect(_endpoint, connect_handler);
_ios.run();
}
// read write data (?)
}
处理程序:
void tcpclient::connect_handler(const boost::system::error_code &error) {
if(error){
// trigger disconnect (?)
logger::log_error(error.message());
return;
}
// Connection is established at this point
// Update timer state and start authentication on server ?
logger::log_info("Connected?");
}
每次连接失败(或断开)时,如何正确开始重新连接?由于处理程序是静态的,我不能修改指示连接状态的类属性?我想避免使用 hacky 的全局变量解决方法。 我怎样才能以适当的方式解决这个问题?
我的尝试是这样的:
tcpclient.h
enum ConnectionStatus{
NOT_CONNECTED,
CONNECTED
};
class tcpclient {
public:
tcpclient(std::string host, int port);
void start();
private:
ConnectionStatus _status = NOT_CONNECTED;
void connect_handler(const boost::system::error_code& error);
boost::asio::io_service _ios;
boost::asio::ip::tcp::endpoint _endpoint;
boost::asio::ip::tcp::socket _socket;
};
tcpclient.cpp
#include "tcpclient.h"
#include <boost/chrono.hpp>
#include "../utils/logger.h"
tcpclient::tcpclient(std::string host, int port) : _endpoint(boost::asio::ip::address::from_string(host), port),
_socket(_ios) {
logger::log_info("Initiating client ...");
logger::log_info("Server endpoint: " + _endpoint.address().to_string());
}
void tcpclient::connect_handler(const boost::system::error_code &error) {
if(!error){
_status = CONNECTED;
logger::log_info("Connected.");
}
else{
_status = NOT_CONNECTED;
logger::log_info("Failed to connect");
_socket.close();
}
}
void tcpclient::start() {
while (_status == NOT_CONNECTED) {
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
_socket.close();
_socket.async_connect(_endpoint, std::bind(&tcpclient::connect_handler, this, std::placeholders::_1));
_ios.run();
}
}
问题是重新连接无法正常工作并且应用程序似乎由于某种原因冻结?除此之外,一旦建立连接然后断开连接(例如由于服务器崩溃/关闭),重新连接似乎也会出现问题。
【问题讨论】:
标签: c++ asynchronous boost tcp asio