From 778c17811e12d3b22bdd3b5d7b906d247002ba78 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sun, 28 Dec 2025 17:44:41 +0800 Subject: [PATCH] fix: improve handling of client connection failures --- src/network/client/Client.cpp | 64 +++++++++++++++++++++++++++---- src/network/client/Client.h | 4 +- src/network/server/GameServer.cpp | 11 +++++- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/network/client/Client.cpp b/src/network/client/Client.cpp index c2313d6..207cabd 100644 --- a/src/network/client/Client.cpp +++ b/src/network/client/Client.cpp @@ -1,6 +1,7 @@ #include "Client.h" #include Client::Client(asio::io_context& ioContext): + m_ioContext(ioContext), m_resolver(ioContext), m_socket(ioContext) { @@ -90,13 +91,28 @@ void Client::sentClickPosition(const NetData& data, bool isChangeTurn) { } void Client::waitForOpponent() { - if (!m_shouldWait || m_isWaiting) { + if (!m_shouldWait || m_isWaiting || !m_socket.is_open()) { return; } + m_isWaiting = true; + + // 添加调试信息 + std::cout << "DEBUG: Starting to wait for data from " + << m_host << ":" << m_port + << ", socket open: " << m_socket.is_open() + << ", shouldWait: " << m_shouldWait << std::endl; + auto self = shared_from_this(); + + // 设置读取超时 + m_socket.set_option(asio::ip::tcp::no_delay(true)); + m_socket.async_read_some( asio::buffer(m_readBuffer, NetData::size()), [this, self](const asio::error_code& ec, std::size_t bytesTransferred) { + m_isWaiting = false; // 重置等待状态 + std::cout << "DEBUG: Read callback - Bytes received: " + << bytesTransferred << ", Error: " << ec.message() << std::endl; if (!ec) { if (bytesTransferred == NetData::size()) { @@ -145,7 +161,7 @@ void Client::waitForOpponent() { m_onMyTurn(); } } else { - if (m_shouldWait) { + if (m_shouldWait && m_socket.is_open()) { waitForOpponent(); } } @@ -159,13 +175,47 @@ void Client::waitForOpponent() { } } } else { - std::cerr << "read failed: " << ec.message() << std::endl; - // 发生错误时,可以选择重新等待对手 - if (m_shouldWait) { - waitForOpponent(); - } + // 关键修复:区分不同类型的错误 + if (ec == asio::error::eof) { + // 对端正常关闭连接 + std::cout << "Connection closed by peer." << std::endl; + // 不要重试,关闭socket + closeConnection(); + } else if (ec == asio::error::operation_aborted) { + // 操作被取消(正常情况) + std::cout << "Read operation cancelled." << std::endl; + } else { + // 其他错误 + std::cerr << "Read error: " << ec.message() << std::endl; + // 尝试重新连接 + if (m_shouldWait) { + attemptReconnect(); + } } } + } ); + } +void Client::closeConnection() { + asio::error_code ec; + if (m_socket.is_open()) { + m_socket.shutdown(asio::ip::tcp::socket::shutdown_both, ec); + m_socket.close(ec); + } + m_isWaiting = false; + m_shouldWait = false; + std::cout << "Connection closed." << std::endl; +} + +void Client::attemptReconnect() { + std::cout << "Attempting to reconnect to " << m_host << ":" << m_port << "...\n"; + closeConnection(); + // 等待一段时间后重新连接 + auto self = shared_from_this(); + asio::steady_timer timer(m_ioContext, std::chrono::seconds(3)); + 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 8c87749..2e420cd 100644 --- a/src/network/client/Client.h +++ b/src/network/client/Client.h @@ -27,6 +27,7 @@ public: private: + asio::io_context& m_ioContext; // 添加引用 asio::ip::tcp::resolver m_resolver; asio::ip::tcp::socket m_socket; std::string m_host; @@ -47,5 +48,6 @@ 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 06b03cc..7fb224c 100644 --- a/src/network/server/GameServer.cpp +++ b/src/network/server/GameServer.cpp @@ -81,7 +81,16 @@ void GameServer::waitForPlayers(int playerNum) { } void GameServer::startGame() { - std::cout << "Gmae Start player1 is the first\n"; + std::cout << "Game Start player1 is the first\n"; + + // 检查两个socket的状态 + std::cout << "DEBUG: Player1 socket open: " << m_player1.is_open() + << ", remote: " << m_player1.remote_endpoint().address().to_string() + << ":" << m_player1.remote_endpoint().port() << std::endl; + + std::cout << "DEBUG: Player2 socket open: " << m_player2.is_open() + << ", remote: " << m_player2.remote_endpoint().address().to_string() + << ":" << m_player2.remote_endpoint().port() << std::endl; NetData gameStartMsg; gameStartMsg.type = NetDataType::GAME_START;