Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 2.3.1] Projekt klasy służącej do komunikacji sieciowej.

Ostatnio zmodyfikowano 2015-08-29 14:54
Autor Wiadomość
1aam2am1
Temat założony przez niniejszego użytkownika
[SFML 2.3.1] Projekt klasy służącej do komunikacji sieciowej.
» 2015-08-29 01:27:51
Szukam porady jak zmienić, dodać, usunąć, ogólnie ulepszyć mój projekt.
Ostrzegam że nie do końca znam się na nowoczesnym programowaniu. I niemiałem styczności wcześniej z żadnym takim projektem.

Plik Protocol.h
C/C++
#ifndef PACKET_H
#define PACKET_H
#include <SFML/Network/Packet.hpp>


namespace Game_api {
   
    enum Protocol: int32_t
    {
        null = 0,
        identification = 1, //identfikacja aplikacji
       
        message = 5, //wiadomosc
       
        audio = 20, //zapowiedz
       
        //game = 21, //gra
    };
   
    sf::Packet & operator <<( sf::Packet &, const Protocol & );
    sf::Packet & operator >>( sf::Packet &, Protocol & );
   
}
#endif // PACKET_H
Plik Protocol.cpp
C/C++
#include "Protocol.h"

namespace Game_api {
   
    sf::Packet & operator <<( sf::Packet & packet, const Protocol & protocol )
    {
        packet << static_cast < const int32_t &>( protocol );
        return packet;
    }
   
    sf::Packet & operator >>( sf::Packet & packet, Protocol & protocol )
    {
        int32_t tmp;
        packet >> tmp;
        protocol = Protocol( tmp );
        return packet;
    }
   
}

Plik Network_client.h
C/C++
#ifndef NETWORK_CLIENT_H
#define NETWORK_CLIENT_H
#include "Protocol.h"
#include <mutex>

namespace Game_api {
   
    class Network_client
    {
    public:
        virtual ~Network_client() = default;
        virtual void newPacket( sf::Packet & ) = 0;
       
        std::recursive_mutex mutex_;
    protected:
        Network_client() = default;
    };
   
}
#endif // NETWORK_CLIENT_H

Plik Client.h
C/C++
#ifndef CLIENT_H
#define CLIENT_H
#include <SFML/Network/TcpSocket.hpp>
#include <mutex>
#include "Protocol.h"
#include <map>
#include "Network_client.h"
#include <memory>

namespace Game_api {
   
    class Client
        : sf::NonCopyable
    {
    public:
        Client();
        ~Client();
        sf::TcpSocket socket_;
        std::map < Protocol, std::shared_ptr < Network_client >> protocol_table_;
        std::recursive_mutex mutex_;
       
    private:
       
    };
   
   
   
}
#endif // CLIENT_H
Plik Client.cpp
C/C++
#include "Client.h"

namespace Game_api {
   
    Client::Client()
    {
        this->socket_.setBlocking( false );
    }
   
    Client::~Client()
    {
        printf( "Client destoyed\n" );
    }
   
}

Plik Network.h
C/C++
#ifndef NETWORK_H
#define NETWORK_H
#include <functional>
#include <mutex>
#include <list>
#include <map>
#include "Client.h"
#include <string>
#include <thread>
#include <SFML/Network.hpp>
#include <memory>

namespace Game_api {
   
   
    class Identification;
   
    class Network
    {
    public:
        Network();
        ~Network();
       
        bool addObjectToCreationList( Protocol, std::function < std::shared_ptr < Network_client >( std::shared_ptr < Client >, sf::Packet & ) > );
       
        void set_game_type( const Identification * );
       
        std::list < std::shared_ptr < Client >>& get_Connected_list();
       
        std::shared_ptr < Client >& connect( const Identification * );
        std::shared_ptr < Client >& connect( const sf::IpAddress &, const unsigned short & );
       
        template < typename T >
        void send_brodcast( const Protocol &, const T & );
        void send_connected( sf::Packet & );
    private:
        const Identification * identification_;
        unsigned short remotePort_a = 22653; //aplikacja
        unsigned short remotePort_s = 22654; //server
        unsigned short remotePort_sf = 22655; //server plikow
       
        std::thread thread;
        std::thread sp_thread;
        void _thread();
        void _sp_thread();
        bool close = 0;
       
        sf::TcpListener listener; //nasluchuje portow tcp
        sf::UdpSocket udp; //nasluchuje i wysyla informacje udp
        sf::SocketSelector selector; //nasluchuje informacji z polaczen
       
        std::list < std::shared_ptr < Client >> connected_list;
        std::map < Protocol, std::function < std::shared_ptr < Network_client >( std::shared_ptr < Client >, sf::Packet & ) >> creationMap_;
       
    private:
        std::recursive_mutex mutex_;
    };
   
    extern Network network;
   
}
#endif // NETWORK_H

Plik Network.cpp
C/C++
#include "Network.h"
#include "Identification.h"

namespace Game_api {
   
    Network network;
   
    Network::Network()
    {
        this->listener.listen( 0 );
        this->selector.add( this->listener );
       
        this->udp.bind( 0 );
        this->selector.add( this->udp );
    }
   
    Network::~Network()
    {
        {
            std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
            this->close = 1; //kill
        }
        if( this->thread.joinable() )
        {
            this->thread.join();
        }
       
        if( this->sp_thread.joinable() )
        {
            this->sp_thread.join();
        }
    }
   
    bool Network::addObjectToCreationList( Protocol i, std::function < std::shared_ptr < Network_client >( std::shared_ptr < Client >, sf::Packet & ) > a )
    {
        std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
       
        this->creationMap_[ i ] = a;
        return true;
    }
   
    std::list < std::shared_ptr < Client >>& Network::get_Connected_list()
    {
        std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
       
        return this->connected_list;
    }
   
    void Network::send_connected( sf::Packet & packet )
    {
        std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
       
        for( auto it = this->connected_list.begin(); it != this->connected_list.end(); ++it )
        {
            std::lock_guard < std::recursive_mutex > lock(( * it )->mutex_ );
            ( * it )->socket_.send( packet );
        }
    }
   
    std::shared_ptr < Client >& Network::connect( const Identification * identification )
    {
        std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
       
        this->connected_list.push_back( std::shared_ptr < Client >( new Client ) );
       
        this->connected_list.back()->socket_.connect( identification->ipaddress_local, identification->port, sf::milliseconds( 500 ) ); //popraw
        this->selector.add( this->connected_list.back()->socket_ );
       
        return this->connected_list.back();
    }
   
    std::shared_ptr < Client >& Network::connect( const sf::IpAddress & ipaddress, const unsigned short & port )
    {
        std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
       
        this->connected_list.push_back( std::shared_ptr < Client >( new Client ) );
       
        this->connected_list.back()->socket_.connect( ipaddress, port, sf::milliseconds( 500 ) ); //popraw
        this->selector.add( this->connected_list.back()->socket_ );
       
        return this->connected_list.back();
    }
   
    void Network::_thread()
    {
        {
            std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
           
            unsigned short rm = this->identification_->port;
            if( this->identification_->port == 0 )
            {
                switch( this->identification_->type )
                {
                case Identification::Type::server:
                    rm = this->remotePort_s;
                    break;
                case Identification::Type::client:
                    rm = this->remotePort_a;
                    break;
                case Identification::Type::server_file:
                    rm = this->remotePort_sf;
                    break;
                default:
                    printf( "Nie obslugiwany typ gry\n" );
                    return;
                }
            }
           
            this->selector.remove( this->listener );
            this->listener.close();
            this->listener.listen( rm );
            this->selector.add( this->listener );
           
            this->selector.remove( this->udp );
            this->udp.unbind();
            this->udp.bind( rm );
            this->selector.add( this->udp );
           
            sp_thread = std::thread( & Network::_sp_thread, this ); //launch
        }
       
        this->mutex_.lock(); ///1
        while( !this->close )
        {
            this->mutex_.unlock(); ///2
           
            if( this->selector.wait( sf::milliseconds( 10 ) ) )
            {
                std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
                printf( "Selektor\n" );
               
                if( this->selector.isReady( this->listener ) )
                {
                    this->connected_list.push_back( std::shared_ptr < Client >( new Client ) );
                   
                    if( listener.accept( this->connected_list.back()->socket_ ) == sf::Socket::Done )
                    {
                        printf( "Connected: " + this->connected_list.back()->socket_.getRemoteAddress().toString() + "\n" );
                       
                        this->selector.add( this->connected_list.back()->socket_ );
                       
                        sf::Packet packet;
                        packet << Protocol::identification;
                        packet << * this->identification_;
                        this->connected_list.back()->socket_.send( packet );
                    }
                    else
                    {
                        this->connected_list.pop_back();
                    }
                }
                else
                {
                    printf( "Szukanie poloczenia\n" );
                   
                    for( auto it = connected_list.begin(); it != connected_list.end(); ++it )
                    {
                        if( selector.isReady(( * it )->socket_ ) )
                        {
                            printf( "Znaleziono polaczenie\n" );
                            ( * it )->mutex_.lock();
                            sf::Packet packet;
                            sf::Socket::Status status =( * it )->socket_.receive( packet );
                            if( status == sf::Socket::Status::Disconnected )
                            {
                                printf( "Diskonnect: " +( * it )->socket_.getRemoteAddress().toString() + "\n" );
                                this->selector.remove(( * it )->socket_ );
                                ( * it )->mutex_.unlock();
                                this->connected_list.erase( it++ );
                                if( it == connected_list.end() ) { break; }
                            } else
                            if( status == sf::Socket::Status::Error || status == sf::Socket::Status::NotReady )
                            {
                                printf( "Error | NotReady\n" );
                            } else
                            if( status == sf::Socket::Partial )
                            {
                                printf( "Part of data\n" );
                               
                            } else
                            if( status == sf::Socket::Status::Done )
                            {
                                printf( "Odebrana pakiet z: " +( * it )->socket_.getRemoteAddress().toString() + "\n" );
                                Protocol protocol;
                                packet >> protocol;
                               
                                auto j =( * it )->protocol_table_.find( protocol );
                                if( j ==( * it )->protocol_table_.end() )
                                {
                                    auto k = this->creationMap_.find( protocol );
                                    if( k != this->creationMap_.end() )
                                    {
                                        auto l = k->second( * it, packet );
                                        if( l != nullptr )
                                        {
                                            ( * it )->protocol_table_.emplace( protocol, l );
                                        }
                                    }
                                    else
                                    {
                                        printf( "Nieobslugiwany protocul: %i\n", static_cast < int32_t >( protocol ) );
                                    }
                                }
                                else
                                {
                                    j->second->newPacket( packet );
                                }
                            } //ifelse
                            ( * it )->mutex_.unlock();
                        } //selektor
                    } //for
                } //uzytkownicy
            } //selector wait
           
            this->mutex_.lock();
        }
        this->mutex_.unlock();
    }
   
    void Network::_sp_thread()
    {
        sf::Clock clock;
       
        this->mutex_.lock();
        while( !this->close )
        {
            this->mutex_.unlock();
           
            if( clock.getElapsedTime() > sf::seconds( 2 ) )
            {
                clock.restart();
               
                sf::Packet packet;
                packet << Protocol::identification;
                packet << * this->identification_;
                {
                    std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
                   
                    this->udp.send( packet, sf::IpAddress::Broadcast, remotePort_a ); //do clientow
                    this->udp.send( packet, sf::IpAddress::Broadcast, remotePort_s ); //do servera
                    this->udp.send( packet, sf::IpAddress::Broadcast, remotePort_sf ); //do servera
                }
            }
           
            sf::sleep( sf::milliseconds( 10 ) );
           
            this->mutex_.lock();
        }
        this->mutex_.unlock();
    }
   
    void Network::set_game_type( const Identification * identification )
    {
        {
            std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
            this->close = 1; //kill
        }
        if( this->thread.joinable() )
        {
            this->thread.join();
        }
       
        if( this->sp_thread.joinable() )
        {
            this->sp_thread.join();
        }
       
        std::lock_guard < std::recursive_mutex > lock( this->mutex_ );
        this->identification_ = identification;
        this->close = 0;
        this->thread = std::thread( & Network::_thread, this ); //launch
       
    }
   
   
}
P-137025
DejaVu
» 2015-08-29 13:38:20
Najlepiej to po prostu napisz grę/chat-a/cokolwiek sieciowego i będziesz miał odpowiedź czy Twoje API jest dobre czy wymaga poprawy.
P-137031
1aam2am1
Temat założony przez niniejszego użytkownika
» 2015-08-29 13:58:53
Stworzyłem klasę obsługi czatu i działała. Tylko zastanawiam się czy to jest dobry schemat działania. Czy nie został wymyślony lepszy, a także liczę na pomocną krytykę i wytykanie błędów.
P-137032
DejaVu
» 2015-08-29 14:54:16
Realizuj projekt. Jak będziesz miał problemy wydajnościowe (a będziesz miał) to będziesz wtedy czytał tutoriale jak napisać sieć lepiej.
P-137035
« 1 »
  Strona 1 z 1