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.
This commit is contained in:
Kayne Ruse
2013-06-17 10:00:07 +10:00
parent 009e7b845b
commit 3d92fb77b3
6 changed files with 134 additions and 66 deletions
+1 -3
View File
@@ -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"));
}
+1
View File
@@ -62,6 +62,7 @@ protected:
std::vector<ServerEntry> serverList;
ServerEntry* selectedServer = nullptr;
//threads
SDL_Thread* queueThread = nullptr;
};
+3
View File
@@ -145,7 +145,10 @@ void SceneManager::Quit() {
surfaceMgr = ServiceLocator<SurfaceManager>::Set(nullptr);
netUtil = ServiceLocator<UDPNetworkUtility>::Set(nullptr);
//clean up the scene
UnloadScene();
//deinitialize the APIs
SDLNet_Quit();
SDL_Quit();
}
+7
View File
@@ -7,12 +7,19 @@
#include <deque>
#ifdef DEBUG
#include <iostream>
#endif
static SDL_sem* lock = SDL_CreateSemaphore(1);
static std::deque<Packet> queue;
int networkQueue(void*) {
UDPNetworkUtility* netUtil = ServiceLocator<UDPNetworkUtility>::Get();
#ifdef DEBUG
std::cout << "int networkQueue(void*) active" << std::endl;
#endif
for(;;) {
SDL_SemWait(lock);
while(netUtil->Receive()) {
+109 -60
View File
@@ -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<ConfigUtility>::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<UDPNetworkUtility>::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<ConfigUtility>::Set(nullptr);
netUtil = ServiceLocator<UDPNetworkUtility>::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));
}
+13 -3
View File
@@ -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 <map>
#include <chrono>
@@ -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<int, ClientData> clients;
std::map<int, PlayerData> players;
ConfigUtility configUtil;
UDPNetworkUtility netUtil;
bool running = false;
//threads
SDL_Thread* queueThread = nullptr;
};
#endif