gpt4 book ai didi

c++ - 如何在断开连接后干净地重新连接 boost::socket?

转载 作者:IT老高 更新时间:2023-10-28 12:57:05 24 4
gpt4 key购买 nike

我的客户端应用程序使用 boost::asio::ip::tcp::socket 连接到远程服务器。如果应用程序失去与该服务器的连接(例如,由于服务器崩溃或关闭),我希望它定期尝试重新连接,直到成功。

我需要在客户端做什么才能彻底处理断开连接、整理并反复尝试重新连接?

目前我的代码中有趣的部分看起来像这样。

我像这样连接:

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 错误:无效参数”。这仅仅是因为我试图关闭一个没有读/写挂起的套接字吗?还是更多?

最佳答案

每次重新连接时都需要创建一个新的boost::asio::ip::tcp::socket。最简单的方法可能是使用 boost::shared_ptr 在堆上分配套接字(如果你的套接字完全是,你也可以使用 scoped_ptr封装在一个类中)。例如:

bool MyClient::myconnect()
{
bool isConnected = false;

// Attempt connection
// socket is of type boost::shared_ptr<boost::asio::ip::tcp::socket>
socket.reset(new boost::asio::ip::tcp::socket(...));
socket->connect(server_endpoint, errorcode);
// ...
}

然后,当 mydisconnect 被调用时,你可以释放套接字:

void MyClient::mydisconnect(void)
{
// ...
// deallocate socket. will close any open descriptors
socket.reset();
}

您看到的错误可能是操作系统在您调用 close 后清理文件描述符的结果。当您调用 close 然后尝试在同一个套接字上 connect 时,您可能正在尝试连接一个无效的文件描述符。此时,您应该会根据您的逻辑看到一条以“连接失败:...”开头的错误消息,但随后您调用 mydisconnect 可能正在尝试调用 shutdown 在无效的文件描述符上。恶性循环!

关于c++ - 如何在断开连接后干净地重新连接 boost::socket?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3062803/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com