[SFML 2.3.1] Projekt klasy służącej do komunikacji sieciowej.
Ostatnio zmodyfikowano 2015-08-29 14:54
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 #ifndef PACKET_H #define PACKET_H #include <SFML/Network/Packet.hpp>
namespace Game_api { enum Protocol: int32_t { null = 0, identification = 1, message = 5, audio = 20, }; sf::Packet & operator <<( sf::Packet &, const Protocol & ); sf::Packet & operator >>( sf::Packet &, Protocol & ); } #endif
Plik Protocol.cpp #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 #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
Plik Client.h #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
Plik Client.cpp #include "Client.h"
namespace Game_api { Client::Client() { this->socket_.setBlocking( false ); } Client::~Client() { printf( "Client destoyed\n" ); } }
Plik Network.h #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; unsigned short remotePort_s = 22654; unsigned short remotePort_sf = 22655; std::thread thread; std::thread sp_thread; void _thread(); void _sp_thread(); bool close = 0; sf::TcpListener listener; sf::UdpSocket udp; sf::SocketSelector selector; 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
Plik Network.cpp #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; } 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 ) ); 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 ) ); 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 ); } this->mutex_.lock(); while( !this->close ) { this->mutex_.unlock(); 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 ); } } ( * it )->mutex_.unlock(); } } } } 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 ); this->udp.send( packet, sf::IpAddress::Broadcast, remotePort_s ); this->udp.send( packet, sf::IpAddress::Broadcast, remotePort_sf ); } } 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; } 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 ); } }
|
|
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. |
|
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. |
|
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. |
|
« 1 » |