重构Steam网络管理,整合房间管理功能,添加多路复用支持,优化TCP服务器和消息处理

This commit is contained in:
Ayndpa
2025-11-19 16:49:36 +08:00
parent 0e65ecb8ca
commit f661b1d369
12 changed files with 217 additions and 192 deletions

View File

@@ -57,35 +57,9 @@ void SteamMessageHandler::pollMessages() {
ISteamNetworkingMessage* pIncomingMsg = pIncomingMsgs[i];
const char* data = (const char*)pIncomingMsg->m_pData;
size_t size = pIncomingMsg->m_cbSize;
// Normal forwarding
if (server_) {
server_->sendToAll((const char*)pIncomingMsg->m_pData, pIncomingMsg->m_cbSize);
}
// Lazy connect: Create TCP Client on first message if not already connected
if (clientMap_.find(conn) == clientMap_.end() && g_isHost_ && localPort_ > 0) {
auto client = std::make_shared<TCPClient>("localhost", localPort_);
if (client->connect()) {
client->setReceiveCallback([conn, this](const char* data, size_t size) {
std::lock_guard<std::mutex> lock(clientMutex_);
m_pInterface_->SendMessageToConnection(conn, data, size, k_nSteamNetworkingSend_Reliable, nullptr);
});
client->setDisconnectCallback([conn, this]() {
std::lock_guard<std::mutex> lock(clientMutex_);
if (clientMap_.count(conn)) {
clientMap_[conn]->disconnect();
clientMap_.erase(conn);
std::cout << "TCP client disconnected, removed from map" << std::endl;
}
});
clientMap_[conn] = client;
std::cout << "Created TCP Client for connection on first message" << std::endl;
} else {
std::cerr << "Failed to connect TCP Client for connection" << std::endl;
}
}
// Send to corresponding TCP client if exists (for host)
if (clientMap_.count(conn)) {
clientMap_[conn]->send((const char*)pIncomingMsg->m_pData, pIncomingMsg->m_cbSize);
// Handle tunnel packets with multiplexing
if (server_ && server_->getMultiplexManager()) {
server_->getMultiplexManager()->handleTunnelPacket(data, size);
}
pIncomingMsg->Release();
}

View File

@@ -16,8 +16,7 @@ void SteamNetworkingManager::OnSteamNetConnectionStatusChanged(SteamNetConnectio
SteamNetworkingManager::SteamNetworkingManager()
: m_pInterface(nullptr), hListenSock(k_HSteamListenSocket_Invalid), g_isHost(false), g_isClient(false), g_isConnected(false),
g_hConnection(k_HSteamNetConnection_Invalid),
io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr),
roomManager_(nullptr)
io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr)
{
std::cout << "Initialized SteamNetworkingManager" << std::endl;
}
@@ -26,7 +25,6 @@ SteamNetworkingManager::~SteamNetworkingManager()
{
stopMessageHandler();
delete messageHandler_;
delete roomManager_;
shutdown();
}
@@ -85,36 +83,19 @@ bool SteamNetworkingManager::initialize()
&allowWithoutAuth);
// Create callbacks after Steam API init
roomManager_ = new SteamRoomManager(this);
SteamNetworkingUtils()->InitRelayNetworkAccess();
SteamNetworkingUtils()->SetGlobalCallback_SteamNetConnectionStatusChanged(OnSteamNetConnectionStatusChanged);
m_pInterface = SteamNetworkingSockets();
// Clear Rich Presence on startup
SteamFriends()->ClearRichPresence();
std::cout << "Cleared Rich Presence on startup" << std::endl;
// Check if callbacks are registered
std::cout << "Steam API initialized" << std::endl;
// Get friends list
int friendCount = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
for (int i = 0; i < friendCount; ++i)
{
CSteamID friendID = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(friendID);
friendsList.push_back({friendID, name});
}
return true;
}
void SteamNetworkingManager::shutdown()
{
if (roomManager_)
roomManager_->leaveLobby();
if (g_hConnection != k_HSteamNetConnection_Invalid)
{
m_pInterface->CloseConnection(g_hConnection, 0, nullptr, false);
@@ -123,66 +104,9 @@ void SteamNetworkingManager::shutdown()
{
m_pInterface->CloseListenSocket(hListenSock);
}
// Clear Rich Presence on shutdown
SteamFriends()->ClearRichPresence();
SteamAPI_Shutdown();
}
bool SteamNetworkingManager::createLobby()
{
if (roomManager_)
return roomManager_->createLobby();
return false;
}
void SteamNetworkingManager::leaveLobby()
{
if (roomManager_)
roomManager_->leaveLobby();
}
bool SteamNetworkingManager::searchLobbies()
{
if (roomManager_)
return roomManager_->searchLobbies();
return false;
}
bool SteamNetworkingManager::joinLobby(CSteamID lobbyID)
{
if (roomManager_)
return roomManager_->joinLobby(lobbyID);
return false;
}
const std::vector<CSteamID>& SteamNetworkingManager::getLobbies() const
{
static std::vector<CSteamID> empty;
if (roomManager_)
return roomManager_->getLobbies();
return empty;
}
CSteamID SteamNetworkingManager::getCurrentLobby() const
{
if (roomManager_)
return roomManager_->getCurrentLobby();
return k_steamIDNil;
}
bool SteamNetworkingManager::startHosting()
{
if (roomManager_)
return roomManager_->startHosting();
return false;
}
void SteamNetworkingManager::stopHosting()
{
if (roomManager_)
roomManager_->stopHosting();
}
bool SteamNetworkingManager::joinHost(uint64 hostID)
{
CSteamID hostSteamID(hostID);

View File

@@ -9,9 +9,7 @@
#include <isteamnetworkingsockets.h>
#include <isteamnetworkingutils.h>
#include <steamnetworkingtypes.h>
#include <isteammatchmaking.h>
#include "steam_message_handler.h"
#include "steam_room_manager.h"
// Forward declarations
class TCPClient;
@@ -35,18 +33,6 @@ public:
bool initialize();
void shutdown();
// Hosting
bool startHosting();
void stopHosting();
// Lobby
bool createLobby();
void leaveLobby();
bool searchLobbies();
bool joinLobby(CSteamID lobbyID);
const std::vector<CSteamID>& getLobbies() const;
CSteamID getCurrentLobby() const;
// Joining
bool joinHost(uint64 hostID);
void disconnect();
@@ -55,12 +41,21 @@ public:
bool isHost() const { return g_isHost; }
bool isClient() const { return g_isClient; }
bool isConnected() const { return g_isConnected; }
const std::vector<std::pair<CSteamID, std::string>>& getFriendsList() const { return friendsList; }
const std::map<HSteamNetConnection, UserInfo>& getUserMap() const { return userMap; }
const std::vector<HSteamNetConnection>& getConnections() const { return connections; }
HSteamNetConnection getConnection() const { return g_hConnection; }
ISteamNetworkingSockets* getInterface() const { return m_pInterface; }
// For SteamRoomManager access
std::unique_ptr<TCPServer>*& getServer() { return server_; }
int*& getLocalPort() { return localPort_; }
boost::asio::io_context*& getIOContext() { return io_context_; }
std::map<HSteamNetConnection, std::shared_ptr<TCPClient>>*& getClientMap() { return clientMap_; }
std::mutex*& getClientMutex() { return clientMutex_; }
HSteamListenSocket& getListenSock() { return hListenSock; }
ISteamNetworkingSockets* getInterface() { return m_pInterface; }
bool& getIsHost() { return g_isHost; }
void setMessageHandlerDependencies(boost::asio::io_context& io_context, std::map<HSteamNetConnection, std::shared_ptr<TCPClient>>& clientMap, std::mutex& clientMutex, std::unique_ptr<TCPServer>& server, int& localPort);
// Message handler
@@ -74,9 +69,6 @@ public:
void setHostSteamID(CSteamID id) { g_hostSteamID = id; }
CSteamID getHostSteamID() const { return g_hostSteamID; }
friend class SteamFriendsCallbacks;
friend class SteamMatchmakingCallbacks;
private:
// Steam API
ISteamNetworkingSockets* m_pInterface;
@@ -99,12 +91,6 @@ private:
const int MAX_RETRIES = 3;
int g_currentVirtualPort;
// Friends
std::vector<std::pair<CSteamID, std::string>> friendsList;
// Room manager
SteamRoomManager* roomManager_;
// Message handler dependencies
boost::asio::io_context* io_context_;
std::map<HSteamNetConnection, std::shared_ptr<TCPClient>>* clientMap_;

View File

@@ -3,7 +3,7 @@
#include <iostream>
#include <algorithm>
SteamFriendsCallbacks::SteamFriendsCallbacks(SteamNetworkingManager *manager) : manager_(manager)
SteamFriendsCallbacks::SteamFriendsCallbacks(SteamNetworkingManager *manager, SteamRoomManager *roomManager) : manager_(manager), roomManager_(roomManager)
{
std::cout << "SteamFriendsCallbacks constructor called" << std::endl;
}
@@ -30,10 +30,10 @@ void SteamFriendsCallbacks::OnGameRichPresenceJoinRequested(GameRichPresenceJoin
{
manager_->joinHost(id);
// Start TCP Server if dependencies are set
if (manager_->server_ && !(*manager_->server_))
if (manager_->getServer() && !(*manager_->getServer()))
{
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
if (!(*manager_->server_)->start())
*manager_->getServer() = std::make_unique<TCPServer>(8888, manager_);
if (!(*manager_->getServer())->start())
{
std::cerr << "Failed to start TCP server" << std::endl;
}
@@ -52,7 +52,7 @@ void SteamFriendsCallbacks::OnGameRichPresenceJoinRequested(GameRichPresenceJoin
if (!manager_->isHost() && !manager_->isConnected())
{
std::cout << "Joining lobby from invite: " << id << std::endl;
manager_->joinLobby(lobbySteamID);
roomManager_->joinLobby(lobbySteamID);
}
else
{
@@ -86,7 +86,7 @@ void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *p
if (!manager_->isHost() && !manager_->isConnected())
{
std::cout << "Joining lobby from request: " << lobbyID.ConvertToUint64() << std::endl;
manager_->joinLobby(lobbyID);
roomManager_->joinLobby(lobbyID);
}
else
{
@@ -99,16 +99,16 @@ void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *p
}
}
SteamMatchmakingCallbacks::SteamMatchmakingCallbacks(SteamNetworkingManager *manager) : manager_(manager) {}
SteamMatchmakingCallbacks::SteamMatchmakingCallbacks(SteamNetworkingManager *manager, SteamRoomManager *roomManager) : manager_(manager), roomManager_(roomManager) {}
void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback)
{
if (pCallback->m_eResult == k_EResultOK)
{
manager_->roomManager_->setCurrentLobby(pCallback->m_ulSteamIDLobby);
std::cout << "Lobby created: " << manager_->roomManager_->getCurrentLobby().ConvertToUint64() << std::endl;
roomManager_->setCurrentLobby(pCallback->m_ulSteamIDLobby);
std::cout << "Lobby created: " << roomManager_->getCurrentLobby().ConvertToUint64() << std::endl;
// Set Rich Presence with lobby ID
std::string lobbyStr = std::to_string(manager_->roomManager_->getCurrentLobby().ConvertToUint64());
std::string lobbyStr = std::to_string(roomManager_->getCurrentLobby().ConvertToUint64());
SteamFriends()->SetRichPresence("connect", lobbyStr.c_str());
SteamFriends()->SetRichPresence("status", "主持游戏房间");
SteamFriends()->SetRichPresence("steam_display", "#StatusWithConnectFormat");
@@ -122,11 +122,11 @@ void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback)
void SteamMatchmakingCallbacks::OnLobbyListReceived(LobbyMatchList_t *pCallback)
{
manager_->roomManager_->clearLobbies();
roomManager_->clearLobbies();
for (uint32 i = 0; i < pCallback->m_nLobbiesMatching; ++i)
{
CSteamID lobbyID = SteamMatchmaking()->GetLobbyByIndex(i);
manager_->roomManager_->addLobby(lobbyID);
roomManager_->addLobby(lobbyID);
}
std::cout << "Received " << pCallback->m_nLobbiesMatching << " lobbies" << std::endl;
}
@@ -135,7 +135,7 @@ void SteamMatchmakingCallbacks::OnLobbyEntered(LobbyEnter_t *pCallback)
{
if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess)
{
manager_->roomManager_->setCurrentLobby(pCallback->m_ulSteamIDLobby);
roomManager_->setCurrentLobby(pCallback->m_ulSteamIDLobby);
std::cout << "Entered lobby: " << pCallback->m_ulSteamIDLobby << std::endl;
// Only join host if not the host
if (!manager_->isHost())
@@ -144,10 +144,10 @@ void SteamMatchmakingCallbacks::OnLobbyEntered(LobbyEnter_t *pCallback)
if (manager_->joinHost(hostID.ConvertToUint64()))
{
// Start TCP Server if dependencies are set
if (manager_->server_ && !(*manager_->server_))
if (manager_->getServer() && !(*manager_->getServer()))
{
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
if (!(*manager_->server_)->start())
*manager_->getServer() = std::make_unique<TCPServer>(8888, manager_);
if (!(*manager_->getServer())->start())
{
std::cerr << "Failed to start TCP server" << std::endl;
}
@@ -165,8 +165,8 @@ SteamRoomManager::SteamRoomManager(SteamNetworkingManager *networkingManager)
: networkingManager_(networkingManager), currentLobby(k_steamIDNil),
steamFriendsCallbacks(nullptr), steamMatchmakingCallbacks(nullptr)
{
steamFriendsCallbacks = new SteamFriendsCallbacks(networkingManager_);
steamMatchmakingCallbacks = new SteamMatchmakingCallbacks(networkingManager_);
steamFriendsCallbacks = new SteamFriendsCallbacks(networkingManager_, this);
steamMatchmakingCallbacks = new SteamMatchmakingCallbacks(networkingManager_, this);
}
SteamRoomManager::~SteamRoomManager()
@@ -227,11 +227,11 @@ bool SteamRoomManager::startHosting()
return false;
}
networkingManager_->hListenSock = networkingManager_->m_pInterface->CreateListenSocketP2P(0, 0, nullptr);
networkingManager_->getListenSock() = networkingManager_->getInterface()->CreateListenSocketP2P(0, 0, nullptr);
if (networkingManager_->hListenSock != k_HSteamListenSocket_Invalid)
if (networkingManager_->getListenSock() != k_HSteamListenSocket_Invalid)
{
networkingManager_->g_isHost = true;
networkingManager_->getIsHost() = true;
std::cout << "Created listen socket for hosting game room" << std::endl;
// Rich Presence is set in OnLobbyCreated callback
return true;
@@ -246,11 +246,11 @@ bool SteamRoomManager::startHosting()
void SteamRoomManager::stopHosting()
{
if (networkingManager_->hListenSock != k_HSteamListenSocket_Invalid)
if (networkingManager_->getListenSock() != k_HSteamListenSocket_Invalid)
{
networkingManager_->m_pInterface->CloseListenSocket(networkingManager_->hListenSock);
networkingManager_->hListenSock = k_HSteamListenSocket_Invalid;
networkingManager_->getInterface()->CloseListenSocket(networkingManager_->getListenSock());
networkingManager_->getListenSock() = k_HSteamListenSocket_Invalid;
}
leaveLobby();
networkingManager_->g_isHost = false;
networkingManager_->getIsHost() = false;
}

View File

@@ -5,28 +5,31 @@
#include <mutex>
class SteamNetworkingManager; // Forward declaration
class SteamRoomManager; // Forward declaration for callbacks
class SteamFriendsCallbacks
{
public:
SteamFriendsCallbacks(SteamNetworkingManager *manager);
SteamFriendsCallbacks(SteamNetworkingManager *manager, SteamRoomManager *roomManager);
void OnGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *pCallback);
void OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback);
private:
SteamNetworkingManager *manager_;
SteamRoomManager *roomManager_;
};
class SteamMatchmakingCallbacks
{
public:
SteamMatchmakingCallbacks(SteamNetworkingManager *manager);
SteamMatchmakingCallbacks(SteamNetworkingManager *manager, SteamRoomManager *roomManager);
void OnLobbyCreated(LobbyCreated_t *pCallback);
void OnLobbyListReceived(LobbyMatchList_t *pCallback);
void OnLobbyEntered(LobbyEnter_t *pCallback);
private:
SteamNetworkingManager *manager_;
SteamRoomManager *roomManager_;
};
class SteamRoomManager

13
steam/steam_utils.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "steam_utils.h"
#include <iostream>
std::vector<std::pair<CSteamID, std::string>> SteamUtils::getFriendsList() {
std::vector<std::pair<CSteamID, std::string>> friendsList;
int friendCount = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
for (int i = 0; i < friendCount; ++i) {
CSteamID friendID = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char* name = SteamFriends()->GetFriendPersonaName(friendID);
friendsList.push_back({friendID, name});
}
return friendsList;
}

9
steam/steam_utils.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <vector>
#include <string>
#include <steam_api.h>
class SteamUtils {
public:
static std::vector<std::pair<CSteamID, std::string>> getFriendsList();
};