سؤال

أنا مهتم بكيفية عمل QTcpServer خلف الكواليس فيما يتعلق بالمواضيع والحظر. QTcpServer لديه listen() الطريقة التي تعود على الفور.إذا بدأ الاستماع بنجاح، فسيقوم الخادم بإصدار الإشارة newConnection().أنا مهتم بكيفية استماع الخادم (هل هو موجود في الموضوع الرئيسي) عندما يكون listen() لقد عادت الطريقة.المثال المعتاد لتطبيق وحدة التحكم مع QTcpServer هو شيء من هذا القبيل:

//main.cpp
int main(int argc, char* argv[])
{
    QCoreApplication app;
    MyServer server;
    app.exec();
}

//MyServer.cpp
MyServer::MyServer(QObject *parent) : QObject(parent)
{
    this->server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()), this, SLOT(on_newConnection()));
    if (!server->listen(QHostAddress::Any, 1234))
        //do something in case of error
}
void MyServer::on_newConnection()
{
    QTcpSocket* socket = server->nextPendingConnection();
    //do some communication...
}

يكون QTcpServer يعتمد على أ QCoreApplication (أو ربما أ QRunLoop) موجود ويعمل لتلقي أحداث الشبكة.هل يمكن أن تعمل بشكل صحيح دون QCoreApplication::exec() يطلق عليها؟

هل كانت مفيدة؟

المحلول

لقد قمت بالتنقيب في الكود المصدري لـ QtCore و QtNetwork وحدات.

بشكل غريب، QTcpServer يمكن أن تعمل في وضعين: متزامن و غير متزامن.

في متزامن الوضع بعد الاتصال listen() يمكن للمتصل الاتصال waitForNewConnection() وهي طريقة حظر (سوف ينام الخيط حتى يتصل شخص ما بمنفذ الاستماع).من هنا QTcpServer يمكن أن تعمل في موضوع دون حلقة الحدث.

في غير متزامن وضع QTcpServer سوف تنبعث منها newConnection() إشارة عند قبول اتصال جديد.ولكن لكي تتمكن من القيام بذلك، يجب أن يكون هناك تشغيل حلقة حدث.الكامنة وراء QCoreApplication هي QEventLoop و QAbstractEventDispatcher (فئة مجردة، نوع ملموس يعتمد على نظام التشغيل، على سبيل المثال QEventDispatcherUNIX).يمكن لمرسل الحدث هذا مراقبة الظروف الموجودة على مآخذ التوصيل (ممثلة بواصفات الملفات).لديها طريقة registerSocketNotifier(QSocketNotifier*).يتم استدعاء هذه الطريقة من قبل منشئ QSocketNotifier الطبقة التي QTcpServer يخلق مثيلا في كل مرة listen() يسمى.استدعاء النظام الوحيد الذي يتم استدعاؤه عند QTcpServer::listen() يتم استدعاءه، بطبيعة الحال، listen() والذي يعود على الفور، كل السحر الحقيقي يحدث عندما تبدأ حلقة الحدث في التشغيل.ستراقب حلقة الحدث (باستخدام المرسل) ما إذا كان هناك شرط معين على المقابس التي تم تسجيلها.ويطلق على select() استدعاء النظام الذي يستقبل واصف ملف واحد أو أكثر ليتم مراقبته (بواسطة النواة) لشروط معينة (إذا كانت هناك بيانات للقراءة، أو إذا كان من الممكن كتابة البيانات، أو إذا حدث خطأ).يمكن أن يقوم الاستدعاء بحظر الخيط حتى يتم استيفاء الشروط على المقابس، أو يمكنه العودة بعد مرور بعض الوقت وعدم استيفاء الشروط على المقابس.لست متأكدًا مما إذا كان كيو تي يتصل أم لا select() مع توفير وقت انتظار أو بدونه (للحظر إلى أجل غير مسمى)، أعتقد أنه يتم تحديده بطريقة معقدة وقابلة للتغيير.لذا، عندما يتم استيفاء الشرط على المقبس أخيرًا، سيقوم مرسل الحدث بإخطار QSocketNotifier لهذا المقبس، والذي، في الخرشنة، سوف يخطر QTcpServer من يستمع إلى المقبس الذي سيقبل الاتصال ويصدر newConnection() الإشارة.


لذلك QTcpServer لا يستدعي نفسه نظام مراقبة حلقة الحدث/المقبس، ولكنه يعتمد عليه عبر QSocketNotifier الذي يستخدمه لتلقي الاتصالات غير المتزامنة.

عندما طريقة متزامنة waitForNewConnection() ويطلق عليه مجرد تجاوز كافة QSocketNotifier الاشياء والمكالمات accept() الذي يمنع الخيط حتى يكون هناك اتصال وارد.

نصائح أخرى

معظم qt's "وراء الكواليس" وظيفة يحدث داخل حلقة الحدث الرئيسية في QCOReApplication: إشارات / فتحات، مؤقتات، إلخ.
مثال على ذلك سيكون JavaScript - يمكنك ربط حدث، لكن حلقة الحدث تتم معالجتها بواسطة المتصفح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top