Przeszukujełem kod źródłowy modułów QtCore
i QtNetwork
.
Aperantly, QTcpServer
może pracować w dwóch trybach: synchroniczny i asynchroniczne.
W trybie synchronicznym po wywołaniu listen()
rozmówcy mogą dzwonić waitForNewConnection()
który jest metoda blokująca (nitka będzie spać dopóki ktoś podłącza się do portu słuchanie). W ten sposób QTcpServer
może pracować w wątku bez pętli zdarzeń.
W trybie asynchronicznym tryb QTcpServer
będzie emitować sygnał newConnection()
po zaakceptowaniu nowego połączenia. Ale aby to zrobić, musi być uruchomiona pętla zdarzeń. U podstaw QCoreApplication
są QEventLoop
i QAbstractEventDispatcher
(klasa abstrakcyjna, typ betonu zależy od systemu operacyjnego, na przykład QEventDispatcherUNIX
). Ten moduł rozsyłający zdarzenia może monitorować warunki na gniazdach (reprezentowane przez deskryptory plików). Ma metodę registerSocketNotifier(QSocketNotifier*)
. Ta metoda jest wywoływana przez konstruktor klasy QSocketNotifier
, która QTcpServer
tworzy instancję za każdym razem, gdy wywoływana jest nazwa listen()
. Jedynym wywołaniem systemowym wywoływanym podczas wywoływania QTcpServer::listen()
jest oczywiście listen()
, który po prostu natychmiast wraca, cała prawdziwa magia ma miejsce, gdy pętla zdarzeń zaczyna działać. Pętla zdarzeń (za pomocą modułu rozsyłającego) monitoruje, czy na zarejestrowanych gniazdach występuje pewien stan. Wywołuje on wywołanie systemowe, które odbiera jeden lub więcej deskryptorów plików, które mają być monitorowane (przez jądro) pod pewnymi warunkami (jeśli istnieją dane do odczytania, czy dane mogą zostać zapisane lub wystąpił błąd). Połączenie może zablokować wątek do momentu spełnienia warunków na gniazdach lub może powrócić po upływie pewnego czasu, a warunki na gniazdach nie zostały spełnione. Nie jestem pewien, czy Qt wywołuje select()
z czasem oczekiwania dostarczonym lub bez (do blokowania w nieskończoność), myślę, że to jest określone w pewien skomplikowany sposób i zmienne. Kiedy wreszcie warunek na gnieździe zostanie spełniony, program rozsyłający zdarzenia powiadomi o tym QSocketNotifier
dla tego gniazda, które powiadomi o tym QTcpServer
, który nasłuchuje gniazda, które zaakceptuje połączenie i wyśle sygnał newConnection()
.
Więc QTcpServer
sama nie zadzwonić do pętli zdarzeń/systemu monitorowania gniazda, ale to zależy od niego poprzez QSocketNotifier
którego używa do asynchronicznego ODBIORCZA połączeń.
Po wywołaniu metody synchronicznej waitForNewConnection()
po prostu omija wszystkie rzeczy QSocketNotifier
i wywołuje accept()
, która blokuje wątek, dopóki nie pojawi się połączenie przychodzące.
Bardzo ładne. Teraz rozumiem, dlaczego wywoływanie nasłuchu przed wykonaniem pętli zdarzeń aplikacji w Qt (używam PyQt) spowodowało, że nie otrzymałem sygnału 'newConnection'. Dzięki za kopanie. – Trilarion