تصميم خادم الدردشة للحلقة "الرئيسية"
-
01-10-2019 - |
سؤال
أنا أكتب على خادم دردشة TCP صغير ، لكنني أواجه بعض المشكلات التي لا يمكنني معرفة كيفية حلها "بأناقة".
فيما يلي رمز الحلقة الرئيسية الخاصة بي: إنها كذلك:
1. يضم متجهًا مع الحدث الأساسي ، الذي تم وضع علامة عليه ، عند إجراء اتصال TCP جديد.
2. يحصل على هذا الاتصال ويدفعه مرة أخرى إلى ناقل أيضًا. ثم مع المقبس ، يقوم بإنشاء كائن CsingLeconnection ويمرر المقبس فيه.
2.1. يحصل على الحدث من CsingLeconnection ، والذي يتم وضع علامة عليه عندما يتلقى الاتصال البيانات ...
3. عندما يتلقى البيانات. تم توجيه الانتظار وإرجاع عدد المقبض في المصفوفة ... مع كل تلك المتجهات الأخرى ، يبدو أنني أستطيع تحديد أي شخص يرسل الآن ...
ولكن كما يمكن للجميع أن يروا: هذه المنهجية سيئة للغاية ... لا يمكنني معرفة كيفية القيام بكل هذا بشكل أفضل ، مع الحصول على مأخذ التوصيل ، وإنشاء اتصال واحد وما إلى ذلك:/...
أي اقتراحات ، تحسينات ، إلخ؟ ...
void CServer::MainLoop()
{
DWORD dwResult = 0;
bool bMainLoop = true;
std::vector<std::string> vecData;
std::vector<HANDLE> vecEvents; //Contains the handles to wait on
std::vector<SOCKET> vecSocks; //contains the sockets
enum
{
ACCEPTOR = 0, //First element: sequence is mandatory
EVENTSIZE //Keep as the last element!
};
//initiate the vector with the basic handles
vecEvents.clear();
GetBasicEvents(vecEvents);
while(bMainLoop)
{
//wait for event handle(s)
dwResult = WaitForMultipleObjects(vecEvents.size(), &vecEvents[0], true, INFINITE);
//New connection(s) made
if(dwResult == (int)ACCEPTOR)
{
//Get the sockets for the new connections
m_pAcceptor->GetOutData(vecSocks);
//Create new connections
for(unsigned int i = 0; i < vecSocks.size(); i++)
{
//Add a new connection
CClientConnection Conn(vecSocks[i]);
m_vecConnections.push_back(Conn);
//Add event
vecEvents.push_back(Conn.GetOutEvent());
}
}
//Data from one of the connections
if(dwResult >= (int)EVENTSIZE)
{
Inc::MSG Msg;
//get received string data
m_vecConnections[dwResult].GetOutData(vecData);
//handle the data
for(unsigned int i = 0; i < vecData.size(); i++)
{
//convert data into message
if(Inc::StringToMessage(vecData[i], Msg) != Inc::SOK)
continue;
//Add the socket to the sender information
Msg.Sender.sock = vecSocks[dwResult];
//Evaluate and delegate data and task
EvaluateMessage(Msg);
}
}
}
}
المحلول
لا تعيد اختراع العجلة ، استخدم Boost.Asio. تم تحسينه جيدًا باستخدام ميزات kernel المحددة لأنظمة التشغيل المختلفة ، وهي مصممة بالطريقة التي تجعل بنية رمز العميل بسيطة. هناك الكثير من الأمثلة والوثائق ، لذلك لا يمكنك أن تخطئ.