我的客户端应用程序使用 boost::asio::ip::tcp::socket
连接到远程服务器。如果应用程序失去与此服务器的连接(例如,由于服务器崩溃或关闭),我希望它定期尝试重新连接,直到成功。
我需要在客户端做什么才能干净地处理断开连接,整理然后反复尝试重新连接?
目前我的代码中有趣的部分看起来像这样。
我 connect
像这样:
bool MyClient::myconnect()
{
bool isConnected = false;
// Attempt connection
socket.connect(server_endpoint, errorcode);
if (errorcode)
{
cerr << "Connection failed: " << errorcode.message() << endl;
mydisconnect();
}
else
{
isConnected = true;
// Connected so setup async read for an incoming message.
startReadMessage();
// And start the io_service_thread
io_service_thread = new boost::thread(
boost::bind(&MyClient::runIOService, this, boost::ref(io_service)));
}
return (isConnected)
}
runIOServer()
方法只是:
void MyClient::runIOService(boost::asio::io_service& io_service)
{
size_t executedCount = io_service.run();
cout << "io_service: " << executedCount << " handlers executed." << endl;
io_service.reset();
}
如果任何异步读取处理程序返回错误,那么他们只需调用此 disconnect
方法:
void MyClient::mydisconnect(void)
{
boost::system::error_code errorcode;
if (socket.is_open())
{
// Boost documentation recommends calling shutdown first
// for "graceful" closing of socket.
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
if (errorcode)
{
cerr << "socket.shutdown error: " << errorcode.message() << endl;
}
socket.close(errorcode);
if (errorcode)
{
cerr << "socket.close error: " << errorcode.message() << endl;
}
// Notify the observer we have disconnected
myObserver->disconnected();
}
..它尝试优雅地断开连接,然后通知观察者,观察者将开始以五秒的间隔调用 connect()
直到重新连接。
还有什么我需要做的吗?
目前这 似乎 确实有效。如果我杀死它所连接的服务器,我会在我的读取处理程序中得到预期的 "End of file"
错误,并且调用 mydisconnect()
没有任何问题。
但是当它尝试重新连接并失败时,我看到它报告 "socket.shutdown error: Invalid argument"
。这仅仅是因为我试图关闭一个没有读/写挂起的套接字吗?还是更多?
原文由 GrahamS 发布,翻译遵循 CC BY-SA 4.0 许可协议
每次重新连接时,您都需要创建一个新的
boost::asio::ip::tcp::socket
。最简单的方法可能是使用boost::shared_ptr
在堆上分配套接字(如果你的套接字完全封装在一个类中,你也可以使用scoped_ptr
) .例如:然后,当调用
mydisconnect
时,您可以释放套接字:您看到的错误可能是操作系统在您调用
close
后清理文件描述符的结果。当您在同一个套接字上调用close
然后尝试connect
时,您可能正在尝试连接无效的文件描述符。此时,根据您的逻辑,您应该会看到一条以“连接失败:…”开头的错误消息,但随后您调用mydisconnect
这可能正在尝试调用shutdown
无效的文件描述符。恶性循环!