From afa3528440b574b4c1051a81946d2c3a929141c1 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sun, 4 Jan 2026 22:52:54 +0800 Subject: [PATCH] refactor: improve resource cleanup logic on network battle exit --- src/network/NetworkManager.cpp | 25 +++++++++++++++++++++++- src/network/NetworkManager.h | 5 ++++- src/network/client/Client.cpp | 6 +++++- src/network/client/Client.h | 4 ++-- src/network/server/GameServer.cpp | 32 ++++++++++++++++++++++++++++++- src/network/server/GameServer.h | 4 ++-- 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/network/NetworkManager.cpp b/src/network/NetworkManager.cpp index 01ebfe5..2d5703a 100644 --- a/src/network/NetworkManager.cpp +++ b/src/network/NetworkManager.cpp @@ -1,4 +1,5 @@ #include "NetworkManager.h" + #include "utils/ConfigLoader.h" #include NetworkManager::NetworkManager() @@ -9,10 +10,30 @@ NetworkManager::NetworkManager() } NetworkManager::~NetworkManager() { + std::cout << "NetworkManager destructor called\n"; + + // 1. 先取消所有异步操作 + if (m_gameServer) { + m_gameServer->stop(); + } + + if (m_client) { + m_client->closeConnection(); + } + + // 2. 等待一小段时间让异步操作处理完成 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // 3. 停止 io_context m_ioContext.stop(); + + // 4. 等待线程结束 if (m_ioThread.joinable()) { m_ioThread.join(); + std::cout << "Network thread joined\n"; } + + std::cout << "NetworkManager destroyed\n"; } void NetworkManager::init(NetType type) { @@ -101,9 +122,11 @@ void NetworkManager::startClient() { } std::cout << "start client success\n"; startIOContextLoop(); + } void NetworkManager::startIOContextLoop() { + m_ioThread = std::thread([this]() { try { @@ -136,4 +159,4 @@ void NetworkManager::setIsMyTurn(bool isMyTurn) { m_client->setShouldWait(!isMyTurn); } -} \ No newline at end of file +} diff --git a/src/network/NetworkManager.h b/src/network/NetworkManager.h index 02558e6..c398645 100644 --- a/src/network/NetworkManager.h +++ b/src/network/NetworkManager.h @@ -3,6 +3,9 @@ #include "network/client/Client.h" #include "network/server/GameServer.h" #include "utils/Config.h" +#include +#include + class NetworkManager { public: using ClickEventCallback = std::function; @@ -47,4 +50,4 @@ private: void startClient(); void startIOContextLoop(); -}; \ No newline at end of file +}; diff --git a/src/network/client/Client.cpp b/src/network/client/Client.cpp index 207cabd..c7ba7cc 100644 --- a/src/network/client/Client.cpp +++ b/src/network/client/Client.cpp @@ -202,6 +202,10 @@ void Client::closeConnection() { asio::error_code ec; if (m_socket.is_open()) { m_socket.shutdown(asio::ip::tcp::socket::shutdown_both, ec); + // 检查错误码 + if (ec && ec != asio::error::not_connected) { + // 处理错误(除了"未连接"之外的错误) + } m_socket.close(ec); } m_isWaiting = false; @@ -218,4 +222,4 @@ void Client::attemptReconnect() { timer.async_wait([this, self](const asio::error_code& /*ec*/) { connect(m_host, m_port, m_isHost); }); -} \ No newline at end of file +} diff --git a/src/network/client/Client.h b/src/network/client/Client.h index 2e420cd..0e1e79a 100644 --- a/src/network/client/Client.h +++ b/src/network/client/Client.h @@ -24,6 +24,7 @@ public: void sentClickPosition(const NetData& data, bool isChangeTurn = false); + void closeConnection(); private: @@ -48,6 +49,5 @@ private: void waitForOpponent(); void stopWaiting(); // 停止等待 - void closeConnection(); void attemptReconnect(); // 尝试重新连接 -}; \ No newline at end of file +}; diff --git a/src/network/server/GameServer.cpp b/src/network/server/GameServer.cpp index 7fb224c..dcd750a 100644 --- a/src/network/server/GameServer.cpp +++ b/src/network/server/GameServer.cpp @@ -132,6 +132,10 @@ void GameServer::forwardMoves() { } void GameServer::listenPlayer(asio::ip::tcp::socket& fromPlayer, asio::ip::tcp::socket& toPlayer) { + // 检查 socket 是否还开着 + if (!fromPlayer.is_open() || !toPlayer.is_open()) { + return; + } auto self = shared_from_this(); fromPlayer.async_read_some( @@ -153,4 +157,30 @@ void GameServer::listenPlayer(asio::ip::tcp::socket& fromPlayer, asio::ip::tcp:: } } ); -} \ No newline at end of file +} + +void GameServer::stop() { + std::cout << "GameServer stopping...\n"; + + // 关闭 socket,这会导致所有 async_read_some 立即返回错误 + asio::error_code ec; + + if (m_player1.is_open()) { + m_player1.cancel(ec); // 取消所有异步操作 + m_player1.shutdown(asio::ip::tcp::socket::shutdown_both, ec); + m_player1.close(ec); + } + + if (m_player2.is_open()) { + m_player2.cancel(ec); + m_player2.shutdown(asio::ip::tcp::socket::shutdown_both, ec); + m_player2.close(ec); + } + + if (m_acceptor.is_open()) { + m_acceptor.cancel(ec); + m_acceptor.close(ec); + } + + std::cout << "GameServer stopped\n"; +} diff --git a/src/network/server/GameServer.h b/src/network/server/GameServer.h index 8d04988..ddf3569 100644 --- a/src/network/server/GameServer.h +++ b/src/network/server/GameServer.h @@ -11,7 +11,7 @@ public: ~GameServer() = default; void startServer( int port); - + void stop(); private: asio::io_context& m_ioContext; //std::unique_ptr m_acceptor; @@ -27,4 +27,4 @@ private: void forwardMoves(); void listenPlayer(asio::ip::tcp::socket& fromPlayer, asio::ip::tcp::socket& toPlayer); -}; \ No newline at end of file +};