From 33474cc6c0524f47c26415ae03252b382a1494d9 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 18 Jun 2013 16:21:42 +1000 Subject: [PATCH] Smooth connection and disconnection complete The clients can connect and disconnect from the server with known no issues. There is no way to shutdown the server yet, but it might be possible to kick someone else from the server soon. --- client/in_world.cpp | 87 +++++++++++++++++++++++++++++++++- client/in_world.hpp | 33 +++++++++++-- client/information_manager.hpp | 1 + client/lobby.cpp | 15 ++---- client/lobby.hpp | 4 +- client/splash_screen.hpp | 2 +- libs/common/defines.cpp | 9 ++++ libs/common/defines.hpp | 3 ++ libs/common/network_queue.cpp | 14 ++++-- libs/common/network_queue.hpp | 7 +-- libs/common/packet_type.hpp | 1 + server/server_application.cpp | 31 ++++++++---- server/server_application.hpp | 3 +- test/main.cpp | 8 +--- 14 files changed, 177 insertions(+), 41 deletions(-) create mode 100644 libs/common/defines.cpp diff --git a/client/in_world.cpp b/client/in_world.cpp index c9429b7..8e6fb5e 100644 --- a/client/in_world.cpp +++ b/client/in_world.cpp @@ -12,6 +12,7 @@ InWorld::InWorld() { #ifdef DEBUG cout << "entering InWorld" << endl; #endif + cout << "Client Index: " << infoMgr->GetClientIndex() << endl; } InWorld::~InWorld() { @@ -29,7 +30,7 @@ void InWorld::FrameStart() { } void InWorld::Update(double delta) { - // + while(HandlePacket(popNetworkPacket())); } void InWorld::FrameEnd() { @@ -44,6 +45,12 @@ void InWorld::Render(SDL_Surface* const screen) { //Event handlers //------------------------- +void InWorld::QuitEvent() { + //ensure that the client is disconnected properly + ExitGame(); + SetNextScene(SceneList::QUIT); +} + void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) { // } @@ -59,7 +66,7 @@ void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) { void InWorld::KeyDown(SDL_KeyboardEvent const& key) { switch(key.keysym.sym) { case SDLK_ESCAPE: - QuitEvent(); + ExitGame(); break; } } @@ -67,3 +74,79 @@ void InWorld::KeyDown(SDL_KeyboardEvent const& key) { void InWorld::KeyUp(SDL_KeyboardEvent const& key) { // } + +//------------------------- +//Utilities +//------------------------- + +int InWorld::HandlePacket(Packet p) { + switch(p.meta.type) { + case PacketType::NONE: + //DO NOTHING + return 0; + break; + case PacketType::PING: + //quick pong + p.meta.type = PacketType::PONG; + netUtil->Send(&p.meta.address, &p, sizeof(Packet)); + break; + case PacketType::PONG: + // + break; +// case PacketType::BROADCAST_REQUEST: +// // +// break; +// case PacketType::BROADCAST_RESPONSE: +// // +// break; +// case PacketType::JOIN_REQUEST: +// // +// break; +// case PacketType::JOIN_RESPONSE: +// // +// break; + case PacketType::DISCONNECT: + HandleDisconnection(p.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: " + itos(int(p.meta.type)))); + } + return 1; +} + +void InWorld::Disconnect() { + //disconnect + Packet p; + p.meta.type = PacketType::DISCONNECT; + p.disconnect.clientIndex = infoMgr->GetClientIndex(); + netUtil->Send(GAME_CHANNEL, reinterpret_cast(&p), sizeof(Packet)); + netUtil->Unbind(GAME_CHANNEL); + endQueueThread(); + + //reset the client + infoMgr->ResetClientIndex(); +} + +void InWorld::ExitGame() { + Disconnect(); + SetNextScene(SceneList::MAINMENU); + cout << "The game session has ended" << endl; +} + +void InWorld::HandleDisconnection(::Disconnect& disconnect) { + Disconnect(); + SetNextScene(SceneList::MAINMENU); + cout << "You have been disconnected" << endl; +} diff --git a/client/in_world.hpp b/client/in_world.hpp index 05f930c..5cee9af 100644 --- a/client/in_world.hpp +++ b/client/in_world.hpp @@ -2,26 +2,53 @@ #define INWORLD_HPP_ #include "base_scene.hpp" +#include "defines.hpp" +#include "service_locator.hpp" +#include "packet_type.hpp" +#include "network_queue.hpp" +#include "information_manager.hpp" + +#include "config_utility.hpp" +#include "surface_manager.hpp" +#include "udp_network_utility.hpp" +#include "button.hpp" +#include "raster_font.hpp" class InWorld : public BaseScene { public: - /* Public access members */ + //Public access members InWorld(); ~InWorld(); protected: - /* Frame loop */ + //Frame loop void FrameStart(); void Update(double delta); void FrameEnd(); void Render(SDL_Surface* const); - /* Event handlers */ + //Event handlers + void QuitEvent(); void MouseMotion(SDL_MouseMotionEvent const&); void MouseButtonDown(SDL_MouseButtonEvent const&); void MouseButtonUp(SDL_MouseButtonEvent const&); void KeyDown(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&); + + //Utilities + int HandlePacket(Packet p); + void Disconnect(); + void ExitGame(); + void HandleDisconnection(::Disconnect&); + + //services + ConfigUtility* configUtil = ServiceLocator::Get(); + SurfaceManager* surfaceMgr = ServiceLocator::Get(); + UDPNetworkUtility* netUtil = ServiceLocator::Get(); + InformationManager* infoMgr = ServiceLocator::Get(); + + //members + //... }; #endif diff --git a/client/information_manager.hpp b/client/information_manager.hpp index 6d48546..967b6a8 100644 --- a/client/information_manager.hpp +++ b/client/information_manager.hpp @@ -5,6 +5,7 @@ class InformationManager { public: int SetClientIndex(int i) { return clientIndex = i; } int GetClientIndex() { return clientIndex; } + void ResetClientIndex() { clientIndex = -1; } private: int clientIndex = -1; }; diff --git a/client/lobby.cpp b/client/lobby.cpp index 5990e28..fcd3a52 100644 --- a/client/lobby.cpp +++ b/client/lobby.cpp @@ -26,12 +26,12 @@ Lobby::Lobby() { serverList.push_back({"bar",{0,0}}); serverList.push_back({"foobar",{0,0}}); - BeginQueueThread(); + flushNetworkQueue(); + beginQueueThread(); BroadcastNetwork(); } Lobby::~Lobby() { - EndQueueThread(); #ifdef DEBUG cout << "leaving Lobby" << endl; #endif @@ -46,13 +46,7 @@ void Lobby::FrameStart() { } void Lobby::Update(double delta) { - try { - //process all packets on the network queue - while(HandlePacket(popNetworkPacket())); - } - catch(exception& e) { - cerr << "Network Error: " << e.what() << endl; - } + while(HandlePacket(popNetworkPacket())); } void Lobby::FrameEnd() { @@ -102,6 +96,7 @@ void Lobby::MouseButtonUp(SDL_MouseButtonEvent const& button) { } else if (backButton.MouseButtonUp(button) == Button::State::HOVER) { SetNextScene(SceneList::MAINMENU); + endQueueThread(); } else if ( //clicked within bounds TODO: make the damn collision system @@ -178,7 +173,7 @@ int Lobby::HandlePacket(Packet p) { // // // break; default: - throw(runtime_error("Failed to recognize the packet type")); + throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type)))); } return 1; } diff --git a/client/lobby.hpp b/client/lobby.hpp index 1fe27f6..6eea9b7 100644 --- a/client/lobby.hpp +++ b/client/lobby.hpp @@ -1,8 +1,8 @@ #ifndef LOBBY_HPP_ #define LOBBY_HPP_ -#include "defines.hpp" #include "base_scene.hpp" +#include "defines.hpp" #include "service_locator.hpp" #include "packet_type.hpp" #include "network_queue.hpp" @@ -14,8 +14,6 @@ #include "button.hpp" #include "raster_font.hpp" -#include "SDL/SDL_thread.h" - #include #include diff --git a/client/splash_screen.hpp b/client/splash_screen.hpp index 0fdd562..f0fa3ed 100644 --- a/client/splash_screen.hpp +++ b/client/splash_screen.hpp @@ -2,8 +2,8 @@ #define SPLASHSCREEN_HPP_ #include "base_scene.hpp" -#include "service_locator.hpp" #include "defines.hpp" +#include "service_locator.hpp" #include "config_utility.hpp" #include "surface_manager.hpp" diff --git a/libs/common/defines.cpp b/libs/common/defines.cpp new file mode 100644 index 0000000..f045d74 --- /dev/null +++ b/libs/common/defines.cpp @@ -0,0 +1,9 @@ +#include "defines.hpp" + +#include + +std::string itos(int i) { + char buffer[20]; + snprintf(buffer, 20, "%d", i); + return std::string(buffer); +} \ No newline at end of file diff --git a/libs/common/defines.hpp b/libs/common/defines.hpp index 3765ced..d803dd9 100644 --- a/libs/common/defines.hpp +++ b/libs/common/defines.hpp @@ -2,10 +2,13 @@ #define DEFINES_HPP #include +#include #define GAME_CHANNEL 0 #define CHAT_CHANNEL 1 typedef std::chrono::high_resolution_clock Clock; +std::string itos(int i); + #endif diff --git a/libs/common/network_queue.cpp b/libs/common/network_queue.cpp index 774d3ba..caf1603 100644 --- a/libs/common/network_queue.cpp +++ b/libs/common/network_queue.cpp @@ -31,7 +31,7 @@ static int networkQueue(void*) { return 0; } -void BeginQueueThread() { +void beginQueueThread() { if (running) { return; } @@ -41,7 +41,7 @@ void BeginQueueThread() { } } -void EndQueueThread() { +void endQueueThread() { if (!running) { return; } @@ -50,7 +50,7 @@ void EndQueueThread() { queueThread = nullptr; } -void KillQueueThread() { +void killQueueThread() { if (!running) { return; } @@ -78,4 +78,12 @@ Packet popNetworkPacket() { } SDL_SemPost(lock); return p; +} + +void flushNetworkQueue() { + UDPNetworkUtility* netUtil = ServiceLocator::Get(); + SDL_SemWait(lock); + while(netUtil->Receive()); + queue.clear(); + SDL_SemPost(lock); } \ No newline at end of file diff --git a/libs/common/network_queue.hpp b/libs/common/network_queue.hpp index 30f6582..0abd517 100644 --- a/libs/common/network_queue.hpp +++ b/libs/common/network_queue.hpp @@ -3,10 +3,11 @@ #include "packet_type.hpp" -void BeginQueueThread(); -void EndQueueThread(); -void KillQueueThread(); +void beginQueueThread(); +void endQueueThread(); +void killQueueThread(); Packet peekNetworkPacket(); Packet popNetworkPacket(); +void flushNetworkQueue(); #endif diff --git a/libs/common/packet_type.hpp b/libs/common/packet_type.hpp index bd62515..ff11d5a 100644 --- a/libs/common/packet_type.hpp +++ b/libs/common/packet_type.hpp @@ -62,6 +62,7 @@ struct JoinResponse { struct Disconnect { Metadata meta; + int clientIndex; }; struct Synchronize { diff --git a/server/server_application.cpp b/server/server_application.cpp index 7fdf66c..326e80b 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -56,7 +56,7 @@ void ServerApplication::Init() { netUtil->Open(configUtil->Int("server.port"), sizeof(Packet)); //create the threads - BeginQueueThread(); + beginQueueThread(); //output the server information cout << configUtil->String("server.name") << endl; @@ -84,7 +84,7 @@ void ServerApplication::Proc() { void ServerApplication::Quit() { //close the threads - EndQueueThread(); + endQueueThread(); //clean up the services netUtil->Close(); @@ -126,7 +126,7 @@ int ServerApplication::HandlePacket(Packet p) { // break; case PacketType::BROADCAST_REQUEST: - Broadcast(p.broadcastRequest); + HandleBroadcast(p.broadcastRequest); break; // case PacketType::BROADCAST_RESPONSE: // // @@ -137,9 +137,9 @@ int ServerApplication::HandlePacket(Packet p) { // case PacketType::JOIN_RESPONSE: // // // break; -// case PacketType::DISCONNECT: -// // -// break; + case PacketType::DISCONNECT: + HandleDisconnection(p.disconnect); + break; // case PacketType::SYNCHRONIZE: // // // break; @@ -153,12 +153,12 @@ int ServerApplication::HandlePacket(Packet p) { // // // break; default: - throw(runtime_error("Failed to recognize the packet type")); + throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type)))); } return 1; } -void ServerApplication::Broadcast(BroadcastRequest& bcast) { +void ServerApplication::HandleBroadcast(BroadcastRequest& bcast) { //respond to a broadcast request with the server's data Packet p; p.meta.type = PacketType::BROADCAST_RESPONSE; @@ -189,6 +189,19 @@ void ServerApplication::HandleConnection(JoinRequest& request) { netUtil->Send(client.channel, &p, sizeof(Packet)); //pretty - cout << "New connection" << endl; + cout << "New connection: index " << client.index << endl; + cout << "number of clients: " << clients.size() << endl; +} + +void ServerApplication::HandleDisconnection(Disconnect& disconnect) { + //disconnect a client (redundant message) + netUtil->Send(clients[disconnect.clientIndex].channel, &disconnect, sizeof(Packet)); + netUtil->Unbind(clients[disconnect.clientIndex].channel); + clients.erase(disconnect.clientIndex); + + //remove the player... + + //pretty + cout << "Lost connection: index " << disconnect.clientIndex << endl; cout << "number of clients: " << clients.size() << endl; } \ No newline at end of file diff --git a/server/server_application.hpp b/server/server_application.hpp index 3b1056f..bbde866 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -50,8 +50,9 @@ private: //network loop int HandlePacket(Packet p); - void Broadcast(BroadcastRequest&); + void HandleBroadcast(BroadcastRequest&); void HandleConnection(JoinRequest&); + void HandleDisconnection(Disconnect&); //services ConfigUtility* configUtil = nullptr; diff --git a/test/main.cpp b/test/main.cpp index 24d0efa..b858b9d 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,11 +1,7 @@ -#include "packet_type.hpp" +#include "defines.hpp" -#include - -using namespace std; int main(int, char**) { - Packet p; - cout << int(p.meta.type) << endl; + std::string s = itos(5); return 0; } \ No newline at end of file