refactor: improve resource cleanup logic on network battle exit

This commit is contained in:
2026-01-04 22:52:54 +08:00
parent bc87dac00a
commit afa3528440
6 changed files with 68 additions and 8 deletions

View File

@@ -1,4 +1,5 @@
#include "NetworkManager.h"
#include "utils/ConfigLoader.h"
#include <iostream>
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);
}
}
}

View File

@@ -3,6 +3,9 @@
#include "network/client/Client.h"
#include "network/server/GameServer.h"
#include "utils/Config.h"
#include <chrono>
#include <thread>
class NetworkManager {
public:
using ClickEventCallback = std::function<void(int logicalX, int logicalY)>;
@@ -47,4 +50,4 @@ private:
void startClient();
void startIOContextLoop();
};
};

View File

@@ -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);
});
}
}

View File

@@ -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(); // 尝试重新连接
};
};

View File

@@ -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::
}
}
);
}
}
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";
}

View File

@@ -11,7 +11,7 @@ public:
~GameServer() = default;
void startServer( int port);
void stop();
private:
asio::io_context& m_ioContext;
//std::unique_ptr<asio::ip::tcp::acceptor> m_acceptor;
@@ -27,4 +27,4 @@ private:
void forwardMoves();
void listenPlayer(asio::ip::tcp::socket& fromPlayer, asio::ip::tcp::socket& toPlayer);
};
};