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 TCPVielleicht 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.