From 3d92fb77b323d4c06cfb0cb4c88620b4a9e7207e Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Mon, 17 Jun 2013 10:00:07 +1000 Subject: [PATCH] Server is multithreaded, but no connection is visible UDPNetworkUtility and ConfigUtility are now using the ServiceLocator pattern in the server, and networkQueue() is running in a separate thread in the server. However, there seems to be a problem somewhere, since the broadcast request & response are not producing any visible output. --- client/lobby.cpp | 4 +- client/lobby.hpp | 1 + client/scene_manager.cpp | 3 + libs/common/network_queue.cpp | 7 ++ server/server_application.cpp | 169 ++++++++++++++++++++++------------ server/server_application.hpp | 16 +++- 6 files changed, 134 insertions(+), 66 deletions(-) diff --git a/client/lobby.cpp b/client/lobby.cpp index d83940a..96b73b8 100644 --- a/client/lobby.cpp +++ b/client/lobby.cpp @@ -26,9 +26,7 @@ Lobby::Lobby() { serverList.push_back({"bar",{0,0}}); serverList.push_back({"foobar",{0,0}}); - queueThread = SDL_CreateThread(networkQueue, nullptr); - - if (!queueThread) { + if (!(queueThread = SDL_CreateThread(networkQueue, nullptr))) { throw(runtime_error("Failed to create the network thread")); } diff --git a/client/lobby.hpp b/client/lobby.hpp index 97663e5..d63a856 100644 --- a/client/lobby.hpp +++ b/client/lobby.hpp @@ -62,6 +62,7 @@ protected: std::vector serverList; ServerEntry* selectedServer = nullptr; + //threads SDL_Thread* queueThread = nullptr; }; diff --git a/client/scene_manager.cpp b/client/scene_manager.cpp index 59374ba..2d46ba4 100644 --- a/client/scene_manager.cpp +++ b/client/scene_manager.cpp @@ -145,7 +145,10 @@ void SceneManager::Quit() { surfaceMgr = ServiceLocator::Set(nullptr); netUtil = ServiceLocator::Set(nullptr); + //clean up the scene UnloadScene(); + + //deinitialize the APIs SDLNet_Quit(); SDL_Quit(); } diff --git a/libs/common/network_queue.cpp b/libs/common/network_queue.cpp index c873732..d9ca069 100644 --- a/libs/common/network_queue.cpp +++ b/libs/common/network_queue.cpp @@ -7,12 +7,19 @@ #include +#ifdef DEBUG +#include +#endif + static SDL_sem* lock = SDL_CreateSemaphore(1); static std::deque queue; int networkQueue(void*) { UDPNetworkUtility* netUtil = ServiceLocator::Get(); +#ifdef DEBUG + std::cout << "int networkQueue(void*) active" << std::endl; +#endif for(;;) { SDL_SemWait(lock); while(netUtil->Receive()) { diff --git a/server/server_application.cpp b/server/server_application.cpp index 0abb981..8a219d0 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -17,22 +17,54 @@ ServerApplication::~ServerApplication() { // } -void ServerApplication::Init() { - if (SDLNet_Init()) { - throw(runtime_error("Failed to initialide SDL_net")); - } +/* ServerApplication::Init() + * This function initializes the entire program. There are a number of things + * that could go wrong here, which is why there is such an unusual order of + * operations. + * Important things to note: + * The APIs are initiated here. + * The global objects are created here. + * The ConfigUtility's call to Load() also ensures that the "rsc\" folder is in the directory. It's easy to forget it. +*/ - configUtil.Load("rsc/config.cfg"); +void ServerApplication::Init() { + //load the config file + try { + configUtil = ServiceLocator::Set(new ConfigUtility()); + configUtil->Load("rsc/config.cfg"); + } + catch(std::runtime_error& e) { + std::string s = e.what(); + s += "; Ensure that the \"rsc\" directory is present"; + throw(std::runtime_error(s)); + } //check the port is valid - if (configUtil.Int("server.port") <= 0) { + if (configUtil->Int("server.port") <= 0) { throw(runtime_error("Cannot open the server on an invalid port or port 0")); } - cout << configUtil["server.name"] << endl; - cout << "Opening on port " << configUtil["server.port"] << endl; - netUtil.Open(configUtil.Int("server.port"), sizeof(Packet)); - //disabled for debugging + //initialize the APIs + if (SDLNet_Init()) { + throw(runtime_error("Failed to initialize SDL_net")); + } + + //instanciate the remaining services + netUtil = ServiceLocator::Set(new UDPNetworkUtility()); + + //initiate the remaining services + netUtil->Open(configUtil->Int("server.port"), sizeof(Packet)); + + //create the threads + if (!(queueThread = SDL_CreateThread(networkQueue, nullptr))) { + throw(runtime_error("Failed to create the network thread")); + } + + //output the server information + cout << configUtil->String("server.name") << endl; + cout << "Open on port " << configUtil->String("server.port") << endl; + + //disable this for debugging running = true; } @@ -40,14 +72,30 @@ void ServerApplication::Proc() { Clock::duration delta = Clock::now() - lastTick; lastTick = Clock::now(); while(running) { - HandleNetwork(); + try { + //process all packets on the network queue + while(HandlePacket(popNetworkPacket())); + } + catch(exception& e) { + cerr << "Network Error: " << e.what() << endl; + } UpdateWorld(double(delta.count()) / Clock::duration::period::den); SDL_Delay(10); } } void ServerApplication::Quit() { - netUtil.Close(); + //close the threads + SDL_KillThread(queueThread); + + //clean up the services + netUtil->Close(); + + //delete the services + configUtil = ServiceLocator::Set(nullptr); + netUtil = ServiceLocator::Set(nullptr); + + //deinitialize the APIs SDLNet_Quit(); } @@ -55,52 +103,6 @@ void ServerApplication::Quit() { //Game loop //------------------------- -void ServerApplication::HandleNetwork() { - Packet p; - while(netUtil.Receive()) { - memcpy(&p, netUtil.GetInData(), sizeof(Packet)); - switch(p.type) { - case PacketType::PING: - //quick pong - p.type = PacketType::PONG; - netUtil.Send(&netUtil.GetInPacket()->address, &p, sizeof(Packet)); - break; - case PacketType::PONG: - // - break; - case PacketType::BROADCAST_REQUEST: - Broadcast(p.broadcastRequest); - break; -// case PacketType::BROADCAST_RESPONSE: -// // -// break; -// case PacketType::JOIN_REQUEST: -// // -// break; -// case PacketType::JOIN_RESPONSE: -// // -// break; -// case PacketType::DISCONNECT: -// // -// break; -// case PacketType::SYNCHRONIZE: -// // -// break; -// case PacketType::PLAYER_NEW: -// // -// break; -// case PacketType::PLAYER_DELETE: -// // -// break; -// case PacketType::PLAYER_MOVE: -// // -// break; - default: - throw(runtime_error("Failed to recognize the packet type")); - } - } -} - void ServerApplication::UpdateWorld(double delta) { for (auto it : players) { it.second.Update(delta); @@ -111,11 +113,58 @@ void ServerApplication::UpdateWorld(double delta) { //Network loop //------------------------- +int ServerApplication::HandlePacket(Packet p) { + switch(p.type) { + case PacketType::NONE: + //DO NOTHING + return 0; + break; + case PacketType::PING: + //quick pong + p.type = PacketType::PONG; + netUtil->Send(&netUtil->GetInPacket()->address, &p, sizeof(Packet)); + break; + case PacketType::PONG: + // + break; + case PacketType::BROADCAST_REQUEST: + Broadcast(p.broadcastRequest); + break; +// case PacketType::BROADCAST_RESPONSE: +// // +// break; +// case PacketType::JOIN_REQUEST: +// // +// break; +// case PacketType::JOIN_RESPONSE: +// // +// break; +// case PacketType::DISCONNECT: +// // +// break; +// case PacketType::SYNCHRONIZE: +// // +// break; +// case PacketType::PLAYER_NEW: +// // +// break; +// case PacketType::PLAYER_DELETE: +// // +// break; +// case PacketType::PLAYER_MOVE: +// // +// break; + default: + throw(runtime_error("Failed to recognize the packet type")); + } + return 1; +} + void ServerApplication::Broadcast(BroadcastRequest& bcast) { //respond to a broadcast request with the server's data Packet p; p.type = PacketType::BROADCAST_RESPONSE; - snprintf(p.broadcastResponse.name, PACKET_STRING_SIZE, "%s", configUtil.CString("server.name")); + snprintf(p.broadcastResponse.name, PACKET_STRING_SIZE, "%s", configUtil->CString("server.name")); //TODO version information - netUtil.Send(&netUtil.GetInPacket()->address, &p, sizeof(Packet)); + netUtil->Send(&netUtil->GetInPacket()->address, &p, sizeof(Packet)); } \ No newline at end of file diff --git a/server/server_application.hpp b/server/server_application.hpp index 51870d3..0ebe084 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -3,11 +3,15 @@ #include "defines.hpp" #include "packet_type.hpp" +#include "service_locator.hpp" +#include "network_queue.hpp" #include "config_Utility.hpp" #include "udp_network_utility.hpp" #include "vector2.hpp" +#include "SDL/SDL_thread.h" + #include #include @@ -39,20 +43,26 @@ public: ServerApplication(ServerApplication const&) = delete; private: //game loop - void HandleNetwork(); void UpdateWorld(double delta); //network loop + int HandlePacket(Packet p); void Broadcast(BroadcastRequest&); + //services + ConfigUtility* configUtil = nullptr; + UDPNetworkUtility* netUtil = nullptr; + + //members Clock::time_point lastTick = Clock::now(); std::map clients; std::map players; - ConfigUtility configUtil; - UDPNetworkUtility netUtil; bool running = false; + + //threads + SDL_Thread* queueThread = nullptr; }; #endif