Boost::Asio - Design vs. Asynchron



  • Hallo,
    und zwar habe ich einen Synchronen TCP-Server, auf den mehrere Clients connecten sollen. Nun bin ich jedoch an dem Punkt, an dem ich nicht weiß ob Asynchronität oder neues Design-Konzept besser wäre. Und zwar geht es um folgende Methode:

    void TCPSyncServer::ListenForSynchronisations()
    {
    	IsConnected = false;
    
    	m_pSocket = new boost::asio::ip::tcp::socket(m_IOService);
    
    	m_pAcceptor->accept(*m_pSocket);
    
    	if(m_pSocket->is_open())
    	{
    		IsConnected = true;
    		++ClientCnt;
    
    		m_ptrlSocket.push_back(m_pSocket);
    
    		std::cout<<"Synchronisated successfully with Client!"<<std::endl;
    
    		for(;;)
    		{
    			m_MsgRecBuffer = GetMessageFromAllClients();
    
    			m_tReceiver::iterator it
    			(
    				m_MsgRecBuffer.begin()
    			);
    
    			for(; it != m_MsgRecBuffer.end(); ++it)
    			{
    				if(it->get<0>() > 0)
    				{
    					std::cout<<"Message from Client["<< it->get<2>() <<"]: ";
    
    					std::vector<char>::size_type loop(0);
    
    					for(; loop != it->get<0>(); ++loop)
    					{
    						if(loop == it->get<0>())
    							std::cout<< it->get<1>()[loop] <<std::endl;
    						else
    							std::cout<< it->get<1>()[loop] <<std::endl;
    					}
    				}
    				else if(it->get<0>() < 0)
    					std::cout<<"[Error] Failed to handle message from client"<<std::endl;
    			}
    		}
    	}
    }
    

    Wie mache ich es nun, dass jederzeit ein Client connecten kann? Ich bin jetzt einfach mal so dreist und poste den kompletten Code, vielleicht hat ja noch einer Verbesserungsvorschläge, denn mir gefällt die Klasse langsam nicht mehr:

    #ifndef TCPSYNCSERVER_HEADER
    #define TCPSYNCSERVER_HEADER
    
    #include "StdIncludes.h"
    
    namespace TCP
    {
    
    typedef std::vector<boost::tuple<std::size_t, 
    								 std::vector<char>, 
    								 unsigned int>> m_tReceiver;
    
    class TCPSyncServer
    {
    	private:
    		unsigned int									  ClientCnt;
    		boost::asio::io_service                           m_IOService;
    		boost::scoped_ptr<boost::asio::ip::tcp::acceptor> m_pAcceptor;
    		boost::asio::ip::tcp::socket					  *m_pSocket;
    		TCPSyncServer::m_tReceiver						  m_MsgRecBuffer; // For output
    		boost::ptr_vector<boost::asio::ip::tcp::socket>   m_ptrlSocket;
    		TCPSyncServer::m_tReceiver                        m_RecMsgVector; // For input
    
    	public:
    		TCPSyncServer(const unsigned int Port = 1337);
    
    		void ListenForSynchronisations();
    
    		void WriteToAllClients(const std::string &Message);
    
    		m_tReceiver GetMessageFromAllClients();
    
    		bool IsConnected;
    };
    
    } // Namespace TCP
    
    #endif TCPSYNCSERVER_HEADER
    #include "TCPSyncServer.h"
    
    namespace TCP
    {
    
    TCPSyncServer::TCPSyncServer(const unsigned int Port) :
    	IsConnected(false),
    	ClientCnt(0)
    {
    	m_pAcceptor.reset
    	(
    		new boost::asio::ip::tcp::acceptor
    		(
    			m_IOService, 
    		    boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), Port)
    		)
    	);
    
    	m_pSocket = new boost::asio::ip::tcp::socket(m_IOService);
    } 
    
    void TCPSyncServer::ListenForSynchronisations()
    {
    	IsConnected = false;
    
    	m_pSocket = new boost::asio::ip::tcp::socket(m_IOService);
    
    	m_pAcceptor->accept(*m_pSocket);
    
    	if(m_pSocket->is_open())
    	{
    		IsConnected = true;
    		++ClientCnt;
    
    		m_ptrlSocket.push_back(m_pSocket);
    
    		std::cout<<"Synchronisated successfully with Client!"<<std::endl;
    
    		for(;;)
    		{
    			m_MsgRecBuffer = GetMessageFromAllClients();
    
    			m_tReceiver::iterator it
    			(
    				m_MsgRecBuffer.begin()
    			);
    
    			for(; it != m_MsgRecBuffer.end(); ++it)
    			{
    				if(it->get<0>() > 0)
    				{
    					std::cout<<"Message from Client["<< it->get<2>() <<"]: ";
    
    					std::vector<char>::size_type loop(0);
    
    					for(; loop != it->get<0>(); ++loop)
    					{
    						if(loop == it->get<0>())
    							std::cout<< it->get<1>()[loop] <<std::endl;
    						else
    							std::cout<< it->get<1>()[loop] <<std::endl;
    					}
    				}
    				else if(it->get<0>() < 0)
    					std::cout<<"[Error] Failed to handle message from client"<<std::endl;
    			}
    		}
    	}
    }
    
    /// Send the message to all clients
    void TCPSyncServer::WriteToAllClients(const std::string &Message)
    {
    	boost::ptr_vector<boost::asio::ip::tcp::socket>::iterator it
    	(
    		m_ptrlSocket.begin()
    	);
    
    	for(; it != m_ptrlSocket.end(); ++it)
    	{
    		boost::asio::write((*it),
    						   boost::asio::buffer(Message),
    						   boost::asio::transfer_all());
    	}
    }
    
    m_tReceiver TCPSyncServer::GetMessageFromAllClients()
    {
    	std::vector<char> Message(1500); // 1,5KB Default size of segment
    	boost::system::error_code ignored_error;
    
    	boost::ptr_vector<boost::asio::ip::tcp::socket>::iterator it
    	(
    		m_ptrlSocket.begin()
    	);
    
    	for(; it != m_ptrlSocket.end(); ++it)
    	{
    		m_RecMsgVector.clear();
    
    		const std::size_t length = it->read_some(boost::asio::buffer(Message),
    												 ignored_error);
    
    		m_RecMsgVector.push_back(boost::make_tuple(length, Message, ClientCnt));
    	}
    
    	if(ignored_error)
    		throw boost::system::system_error(ignored_error);
    
    	return m_RecMsgVector;
    }
    
    } // Namespace TCP
    

    Vielleicht hilft mir ja nochmal mein Schnucki Dravere. Ansonsten danke an Alle im Voraus!



  • Update: Oder soll ich die Endlosschleife einfach in einen Extra-Thread ballern? 😕



  • Habe es jetzt so gemacht, funktioniert eigentlich Prima... 🙂
    Wenn mir jetzt noch einer zum kompletten Design ein paar Tips gibt, dann lecke ich den Bildschirm.

    Danke im Vorrraus (HA! Ausgetricks0rt 😃 )



  • Kannst du dich vielleicht auch mal vernünftig ausdrücken? Wenn man Dinge liest wie "mein Schnucki Dravere", "Endlosschleife in Extra-Thread ballern" und "dann lecke ich den Bildschirm", kann man dich echt nicht mehr ernst nehmen.

    Das ist als netter Hinweis für zukünftige Posts gedacht, also nicht persönlich nehmen.



  • Mich sollte man sowieso nicht Ernst nehmen :p ... aber antworten könnt ihr trotzdem 😃

    EDIT:
    Oh... du fühlst dich vernachlässigt oder? Du darfst auch mein tlayner sein wenn du willst *Kopf treichel*

    Nein ernsthaft, die Fragen waren ernst gemeint. Danke für Antworten!



  • Sind schon Ferien?



  • Kellerkinder wie wir haben immer Zeit! *g*
    Ach ja, Koja ist ja keins... 🙂



  • Es wäre schon net, wenn Du etwas weniger Kot von Dir geben würdest. 😉

    Zum Thema:
    Wenn Du mit einer Endlosschleife in einem extra Thread arbeitest, dann ist das quasi eine schlechte Nachbildung der asynchronen Mechanismen von asio.

    Besser ist es, gleich alles asynchron zu machen.

    Die asynchronen Funktionen haben vor allem den großen Vorteil, dass man sie jederzeit sicher abbrechen kann. Bei den synchronen Funktionen ist das meist gar nicht oder nur mit sehr viel Aufwand möglich.

    Wie man einen asynchronen Server aufbaut, der auch mehrere Clients gleichzeitig verkraften kann, wird z.B. in den HTTP-Server-Beispielen gezeigt.



  • Tachyon schrieb:

    Es wäre schon net, wenn Du etwas weniger Kot von Dir geben würdest. 😉

    Hättet ihr wohl gerne^^

    Tachyon schrieb:

    Wenn Du mit einer Endlosschleife in einem extra Thread arbeitest, dann ist das quasi eine schlechte Nachbildung der asynchronen Mechanismen von asio.

    Hm okay, dachte ich mir schon.

    Tachyon schrieb:

    Die asynchronen Funktionen haben vor allem den großen Vorteil, dass man sie jederzeit sicher abbrechen kann.

    Inwiefern abbrechen?

    Tachyon schrieb:

    Wie man einen asynchronen Server aufbaut, der auch mehrere Clients gleichzeitig verkraften kann, wird z.B. in den HTTP-Server-Beispielen gezeigt.

    Öhmöhmöhm... warum denn HTTP? Über TCP können doch auch mehrere connecten 😕

    Danke soweit erstmal meine kleinen Puffelhäschen 🤡



  • Kóyaánasqatsi schrieb:

    Tachyon schrieb:

    Wie man einen asynchronen Server aufbaut, der auch mehrere Clients gleichzeitig verkraften kann, wird z.B. in den HTTP-Server-Beispielen gezeigt.

    Öhmöhmöhm... warum denn HTTP? Über TCP können doch auch mehrere connecten 😕

    Lies dir nochmal GENAU durch was er geschrieben hat!
    Da steht nicht du sollst jetzt was mit HTTP machen, sondern in die HTTP-Server-examples (wahrscheinlich von boost::asio) schauen, da steht drinnen wie man mit mehreren Clients umgehen kann.



  • @Kóyaánasqatsi: Reiß dich mal zusammen.



  • Kóyaánasqatsi schrieb:

    Öhmöhmöhm... warum denn HTTP? Über TCP können doch auch mehrere connecten 😕

    Weil das eine in der Anwendungsschicht liegt, und das andere in der Transportschicht. Deshalb ist das auch kein Widerspruch zueinander.


Anmelden zum Antworten