fix: improve handling of client connection failures

This commit is contained in:
2025-12-28 17:44:41 +08:00
parent e366d47790
commit 778c17811e
3 changed files with 70 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
#include "Client.h"
#include <iostream>
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);
});
}

View File

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

View File

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