RTYPE TECHNICAL DOCUMENTATION
  • Introduction
  • Classes
    • utils::InputMap
    • utils::Window
    • utils::constant::ButtonValue
    • network::Client
    • network::LockedQueue
    • network::Server
    • ecs::EnemyFactory
    • ecs::Engine
    • ecs::Entity
    • ecs::Event
    • ecs::Registry
    • ecs::SparseArray
    • ecs::World
    • ecs::WorldManager
    • ecs::component::Activable
    • ecs::component::Animated
    • ecs::component::Animated::AnimFrame
    • ecs::component::AttackAI
    • ecs::component::AttackAI::Action
    • ecs::component::AttackAI::AI
    • ecs::component::AttackAI::AI::Pattern
    • ecs::component::Controllable
    • ecs::component::Direction
    • ecs::component::Drawable
    • ecs::component::EntityType
    • ecs::component::Faction
    • ecs::component::FollowEntity
    • ecs::component::Health
    • ecs::component::Hitbox
    • ecs::component::MovementAI
    • ecs::component::MovementAI::AI
    • ecs::component::NetworkId
    • ecs::component::Parallax
    • ecs::component::Position
    • ecs::component::Projectile
    • ecs::component::Score
    • ecs::component::Shootable
    • ecs::component::Size
    • ecs::component::Text
    • ecs::component::textColor
    • ecs::component::Velocity
    • ecs::component::Weapon
    • audio::AudioManager
    • asset::AssetLoader
    • anim::Animation
  • Namespaces
    • utils
    • utils::constant
    • network
    • ecs
    • ecs::component
    • ecs::systems
    • audio
    • asset
    • anim
  • Modules
    • Input
  • Files
    • src
    • src/client
    • Animation.cpp
    • Animation.hpp
    • AssetLoader.cpp
    • AssetLoader.hpp
    • AudioManager.cpp
    • AudioManager.hpp
    • entrypoint.cpp
    • GetWorld.cpp
    • GetWorld.hpp
    • NetworkClient.cpp
    • NetworkClient.hpp
    • src/ecs
    • src/ecs/components
    • src/ecs/components/client
    • Activable.hpp
    • Animated.hpp
    • Controllable.hpp
    • Drawable.hpp
    • Hitbox.hpp
    • Parallax.hpp
    • Shootable.hpp
    • Text.hpp
    • src/ecs/components/server
    • AttackAI.cpp
    • AttackAI.hpp
    • FollowEntity.hpp
    • Projectile.hpp
    • Direction.hpp
    • EntityType.hpp
    • Faction.hpp
    • Health.hpp
    • MovementAI.cpp
    • MovementAI.hpp
    • NetworkId.hpp
    • Position.hpp
    • Score.hpp
    • Size.hpp
    • Velocity.hpp
    • Weapon.hpp
    • src/ecs/systems
    • src/ecs/systems/client
    • Animate.hpp
    • Draw.hpp
    • ExecuteOnce.hpp
    • HandleIncomingMessages.hpp
    • HandleParallaxBounds.hpp
    • HandleSFMLEvents.hpp
    • HandleSFMLKeys.hpp
    • HealthBar.hpp
    • MenuSelect.hpp
    • ScoreUpdate.hpp
    • SendDirection.hpp
    • src/ecs/systems/server
    • DeathUpdate.hpp
    • FollowEntitySystem.hpp
    • HandleIncomingMessage.hpp
    • PlayerHealthUpdate.hpp
    • PositionUpdate.hpp
    • ProjectileCollision.hpp
    • RunAttackAI.hpp
    • Waves.hpp
    • ManageClientEvents.hpp
    • Movement.hpp
    • PositionLogger.hpp
    • RunMovementAI.hpp
    • EnemyFactory.cpp
    • EnemyFactory.hpp
    • Engine.hpp
    • Entity.hpp
    • Event.hpp
    • LockedQueue.hpp
    • Registry.hpp
    • SparseArray.hpp
    • World.hpp
    • WorldManager.cpp
    • WorldManager.hpp
    • src/server
    • entrypoint.cpp
    • Server.cpp
    • Server.hpp
    • src/utils
    • Constant.hpp
    • InputMap.cpp
    • InputMap.hpp
    • Window.cpp
    • README.md
  • Pages
    • deprecated
  • GitHub
Powered by GitBook
On this page
  • Namespaces
  • Classes
  • Types
  • Types Documentation
  • typedef ClientList
  • typedef Client
  • Source code
  1. Files

Server.hpp

Namespaces

Name

Classes

Name

class

Types

Name

typedef std::map< uint32_t, udp::endpoint >

typedef ClientList::value_type

Types Documentation

typedef ClientList

typedef std::map<uint32_t, udp::endpoint> ClientList;

typedef Client

typedef ClientList::value_type Client;

Source code

#pragma once
#include <array>
#include <atomic>
#include <boost/asio.hpp>
#include <boost/asio/post.hpp>
#include <boost/bind/bind.hpp>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include "LockedQueue.hpp"
#include <boost/asio/thread_pool.hpp>
#include <boost/shared_ptr.hpp>

using boost::asio::ip::udp;

typedef std::map<uint32_t, udp::endpoint> ClientList;
typedef ClientList::value_type Client;

namespace network
{
    class Server {
      public:
        ~Server()
        {
            _ioService.stop();
            _serviceThread.join();
            _outgoingService.join();
            _socket.close();
        }

        static bool hasMessages() { return !getInstance()._receivedMessages.empty(); };

        static void sendToClient(const Message &message, uint32_t clientID)
        {
            try {
                getInstance().send(message, getInstance()._clients.at(clientID));
            } catch (std::out_of_range) {
                std::cerr << "sendToClient : Unknown client ID " << clientID << std::endl;
            }
        }

        static void sendToAll(const Message &message)
        {
            for (auto client : getInstance()._clients)
                getInstance().send(message, client.second);
        }

        static size_t getClientCount() { return getInstance()._clients.size(); }

        static uint32_t getClientIdByIndex(size_t index)
        {
            auto it = getInstance()._clients.begin();
            for (int i = 0; i < index; i++)
                ++it;
            return it->first;
        }

        static inline void start(unsigned short localPort)
        {
            if (getInstance()._isRunning)
                return;
            getInstance()._socket = udp::socket(getInstance()._ioService, udp::endpoint(udp::v4(), localPort));
            getInstance()._isRunning = true;
            std::cerr << "Server started on port " << localPort << std::endl;
        }

        static LockedQueue<ServerMessage> &getOutgoingMessages() { return getInstance()._outgoingMessages; }

        static LockedQueue<ClientMessage> &GetReceivedMessages() { return getInstance()._receivedMessages; }

      private:
        LockedQueue<ServerMessage> _outgoingMessages;

        LockedQueue<ClientMessage> _receivedMessages;

        boost::asio::io_service _ioService;
        udp::endpoint _serverEndpoint;
        udp::endpoint _remoteEndpoint;
        Message _recvBuffer;
        udp::socket _socket;

        std::thread _serviceThread;
        std::thread _outgoingService;

        void startReceive()
        {
            _recvBuffer.fill(0);
            _socket.async_receive_from(boost::asio::buffer(_recvBuffer), _remoteEndpoint,
                [this](std::error_code ec, std::size_t bytesRecvd) { this->handleReceive(ec, bytesRecvd); });
        }

        void handleReceive(const std::error_code &error, std::size_t bytesTransferred)
        {
            if (!error) {
                try {
                    auto message = ClientMessage(std::array(_recvBuffer), getOrCreateClientID(_remoteEndpoint));
                    if (!message.first.empty()) {
                        _receivedMessages.push(message);
                        for (const auto &c : message.first) {}
                    }
                } catch (std::exception ex) {
                    std::cerr << "handleReceive: Error parsing incoming message:" << ex.what() << std::endl;
                } catch (...) {
                    std::cerr << "handleReceive: Unknown error while parsing incoming message" << std::endl;
                    ;
                }
            } else {
                std::cerr << "handleReceive: error: " << error.message() << " while receiving from address "
                          << _remoteEndpoint << std::endl;
            }
            startReceive();
        }

        void receiveIncoming()
        {
            while (!_isRunning) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }
            startReceive();
            while (!_ioService.stopped()) {
                try {
                    _ioService.run();
                } catch (const std::exception &e) {
                    std::cerr << "Server: Network exception: " << e.what() << std::endl;
                } catch (...) {
                    std::cerr << "Server: Network exception: unknown" << std::endl;
                }
            }
            std::cerr << "Server network thread stopped" << std::endl;
        }

        int32_t getOrCreateClientID(udp::endpoint endpoint)
        {
            for (const auto &client : _clients)
                if (client.second == endpoint)
                    return client.first;

            auto id = ++_nextClientID;
            _clients.insert(Client(id, endpoint));
            return id;
        }

        void send(const Message &message, udp::endpoint endpoint)
        {
            _socket.async_send_to(
                boost::asio::buffer(message), endpoint, [](std::error_code ec, std::size_t bytesRecvd) {});
        }

        void sendOutgoing()
        {
            while (!_isRunning) {
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }
            while (!_ioService.stopped()) {
                if (!_outgoingMessages.empty()) {
                    ServerMessage message = _outgoingMessages.pop();
                    if (message.second.empty())
                        sendToAll(message.first);
                    else
                        for (auto &client : message.second)
                            sendToClient(message.first, client);
                }
            }
        }

        ClientList _clients;
        int _nextClientID;

        bool _isRunning;

        Server()
            : _socket(_ioService), _isRunning(false), _serviceThread(&network::Server::receiveIncoming, this),
              _nextClientID(0L), _outgoingService(&network::Server::sendOutgoing, this){};

//        static Server getInstance();
        static Server &getInstance();
    };
} // namespace network

Updated on 2022-11-13 at 17:21:37 +0100

PreviousServer.cppNextsrc/utils

Last updated 2 years ago

network
network::Server
ClientList
Client