From f01463bab35620f87222a97d1157daa2f5d71034 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sun, 3 Nov 2013 00:22:38 +1100 Subject: [PATCH] Added and tested the network queue in the server This is a reimplementation of the old network queue, but using a class. This still uses a separate thread, so that packets can wait if there's any lag. Really, thinking about it, I wonder how necessary this was. On the upside, no singletons this time. Which means that you can have several instances of UDPNetworkManager. That's unintentional, but good to know. --- common/network/network_packet.hpp | 6 ++ server/network_queue.cpp | 110 ++++++++++++++++++++++++++++++ server/network_queue.hpp | 35 ++++++++++ server/server_application.cpp | 24 ++++++- server/server_application.hpp | 2 + 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 server/network_queue.cpp create mode 100644 server/network_queue.hpp diff --git a/common/network/network_packet.hpp b/common/network/network_packet.hpp index bf4ad13..0660a87 100644 --- a/common/network/network_packet.hpp +++ b/common/network/network_packet.hpp @@ -68,6 +68,12 @@ union NetworkPacket { char name[PACKET_STRING_SIZE]; //TODO: player count }serverInfo; + + //defaults + NetworkPacket() { + meta.type = Type::NONE; + meta.srcAddress = {0,0}; + } }; #pragma pack(pop) diff --git a/server/network_queue.cpp b/server/network_queue.cpp new file mode 100644 index 0000000..18d254c --- /dev/null +++ b/server/network_queue.cpp @@ -0,0 +1,110 @@ +#include "network_queue.hpp" + +#include "utility.hpp" + +#include +#include + +int networkQueueThread(void* ptr) { + NetworkQueue* netQueue = reinterpret_cast(ptr); + NetworkPacket packet; + + while(netQueue->running) { + SDL_SemWait(netQueue->lock); + + //suck in the waiting packets + while(netQueue->netUtil->Receive()) { + memcpy(&packet, netQueue->netUtil->GetInData(), sizeof(NetworkPacket)); + //this is important: keep track of the source address + packet.meta.srcAddress = netQueue->netUtil->GetInPacket()->address; + netQueue->queue.push_back(packet); + } + + SDL_SemPost(netQueue->lock); + SDL_Delay(10); + } + return 0; +} + +void NetworkQueue::Init(UDPNetworkUtility* ptr) { + if (running) { + throw(std::runtime_error("Network Queue is already running")); + } + running = true; + netUtil = ptr; + lock = SDL_CreateSemaphore(1); + thread = SDL_CreateThread(networkQueueThread, this); + if (!thread) { + throw(std::runtime_error("Failed to create the network thread")); + } +} + +void NetworkQueue::Quit() { + if (!running) { + return; + } + + //end the thread + running = false; + int ret; + SDL_WaitThread(thread, &ret); + + ResetMembers(); + + //handle the return + if (ret != 0) { + throw(std::runtime_error(std::string() + "Network thread returned error code: " + to_string_custom(ret))); + } +} + +void NetworkQueue::Kill() { + if (!running) { + return; + } + + running = false; + SDL_KillThread(thread); + + ResetMembers(); +} + +NetworkPacket NetworkQueue::Peek() { + NetworkPacket ret; + SDL_SemWait(lock); + if (queue.size() > 0) { + ret = queue[0]; + } + SDL_SemPost(lock); + return ret; +} + +NetworkPacket NetworkQueue::Pop() { + NetworkPacket ret; + SDL_SemWait(lock); + if (queue.size() > 0) { + ret = queue[0]; + queue.pop_front(); + } + SDL_SemPost(lock); + return ret; +} + +void NetworkQueue::Flush() { + SDL_SemWait(lock); + while(netUtil->Receive()); + queue.clear(); + SDL_SemPost(lock); +} + +void NetworkQueue::ResetMembers() { + if (running) { + throw(std::logic_error("Cannon reset the queue while running")); + } + + //reset + netUtil = nullptr; + SDL_DestroySemaphore(lock); + lock = nullptr; + thread = nullptr; + queue.clear(); +} diff --git a/server/network_queue.hpp b/server/network_queue.hpp new file mode 100644 index 0000000..6fe2fa1 --- /dev/null +++ b/server/network_queue.hpp @@ -0,0 +1,35 @@ +#ifndef NETWORKQUEUE_HPP_ +#define NETWORKQUEUE_HPP_ + +#include "udp_network_utility.hpp" +#include "network_packet.hpp" + +#include "SDL/SDL_thread.h" + +#include + +class NetworkQueue { +public: + NetworkQueue() = default; + ~NetworkQueue() = default; + + void Init(UDPNetworkUtility*); + void Quit(); + void Kill(); + + NetworkPacket Peek(); + NetworkPacket Pop(); + void Flush(); +private: + friend int networkQueueThread(void*); + void ResetMembers(); + + bool running = false; + + UDPNetworkUtility* netUtil = nullptr; + SDL_sem* lock = nullptr; + SDL_Thread* thread = nullptr; + std::deque queue; +}; + +#endif diff --git a/server/server_application.cpp b/server/server_application.cpp index f10ed5c..d2d4098 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -65,6 +65,7 @@ void ServerApplication::Init(int argc, char** argv) { std::cout << "SDL_net initialized" << std::endl; } networkUtil.Open(21795, 1024); + networkQueue.Init(&networkUtil); //Init SQL std::string dbname = (argc > 1) ? argv[1] : argv[0]; @@ -89,14 +90,35 @@ void ServerApplication::Init(int argc, char** argv) { is.close(); sqlite3_exec(database, script.c_str(), nullptr, nullptr, nullptr); + + //debugging + //create the debug packets + NetworkPacket packet; + + packet.meta.type = NetworkPacket::Type::PING; + strcpy(packet.serverInfo.name,"Foo"); + networkUtil.Send("127.0.0.1", 21795, reinterpret_cast(&packet), sizeof(NetworkPacket)); + strcpy(packet.serverInfo.name,"Bar"); + networkUtil.Send("127.0.0.1", 21795, reinterpret_cast(&packet), sizeof(NetworkPacket)); + strcpy(packet.serverInfo.name,"World"); + networkUtil.Send("127.0.0.1", 21795, reinterpret_cast(&packet), sizeof(NetworkPacket)); + } void ServerApplication::Loop() { - // + //debugging + SDL_Delay(1000); + + NetworkPacket packet; + while(networkQueue.Peek().meta.type != NetworkPacket::Type::NONE) { + packet = networkQueue.Pop(); + std::cout << packet.serverInfo.name << std::endl; + }; } void ServerApplication::Quit() { sqlite3_close_v2(database); + networkQueue.Quit(); networkUtil.Close(); SDLNet_Quit(); SDL_Quit(); diff --git a/server/server_application.hpp b/server/server_application.hpp index 1c7b67e..5328cf4 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -23,6 +23,7 @@ #define SERVERAPPLICATION_HPP_ #include "udp_network_utility.hpp" +#include "network_queue.hpp" #include "sqlite3/sqlite3.h" #include "SDL/SDL.h" @@ -52,6 +53,7 @@ private: sqlite3* database = nullptr; UDPNetworkUtility networkUtil; + NetworkQueue networkQueue; std::list clientEntries; };