Tôi đã khoan qua mã nguồn của các mô-đun QtCore
và QtNetwork
.
Aperantly, QTcpServer
thể làm việc trong hai chế độ: đồng bộ và không đồng bộ.
Trong đồng bộ chế độ sau khi gọi listen()
người gọi có thể gọi waitForNewConnection()
mà là một phương pháp chặn (thread sẽ ngủ cho đến khi ai đó kết nối vào cổng nghe). Bằng cách này, QTcpServer
có thể hoạt động trong một chuỗi không có vòng lặp sự kiện.
Trong không đồng bộ chế độ QTcpServer
sẽ phát ra tín hiệu newConnection()
khi kết nối mới được chấp nhận. Nhưng để có thể thực hiện điều này, phải có một sự kiện chạy vòng lặp. Nằm dưới QCoreApplication
là QEventLoop
và QAbstractEventDispatcher
(một lớp trừu tượng, loại bê tông phụ thuộc vào hệ điều hành, ví dụ: QEventDispatcherUNIX
). Điều phối viên sự kiện này có thể theo dõi các điều kiện trên ổ cắm (được trình bày bởi các bộ mô tả tập tin). Nó có phương thức registerSocketNotifier(QSocketNotifier*)
. Phương thức này được gọi bởi hàm tạo của lớp QSocketNotifier
, trong đó QTcpServer
tạo ra một thể hiện của mọi thời gian listen()
được gọi. Cuộc gọi hệ thống duy nhất được gọi khi QTcpServer::listen()
được gọi là, tất nhiên, listen()
mà chỉ trả về ngay lập tức, tất cả các phép thuật thực sự xảy ra khi vòng lặp sự kiện bắt đầu chạy. Vòng lặp sự kiện (sử dụng bộ điều phối) sẽ theo dõi nếu có một điều kiện nhất định trên các socket đã được đăng ký. Nó gọi là select()
cuộc gọi hệ thống nhận một hoặc nhiều bộ mô tả tệp (theo hạt nhân) cho một số điều kiện nhất định (nếu có dữ liệu được đọc, nếu dữ liệu có thể được ghi hoặc nếu xảy ra lỗi). Cuộc gọi có thể chặn luồng cho đến khi các điều kiện trên các socket được đáp ứng hoặc nó có thể trở lại sau một khoảng thời gian và các điều kiện trên các socket không được đáp ứng. Tôi không chắc chắn nếu Qt đang gọi select()
với thời gian chờ được cung cấp hoặc không có (để chặn vô thời hạn), tôi nghĩ rằng nó được xác định theo một số cách phức tạp và có thể thay đổi. Vì vậy, khi điều kiện cuối cùng trên socket đã được đáp ứng, bộ điều phối sự kiện sẽ thông báo cho QSocketNotifier
cho ổ cắm đó, trong đó, trong tern, thông báo cho QTcpServer
người đang nghe socket, sẽ chấp nhận kết nối và phát ra tín hiệu newConnection()
.
Vì vậy, các QTcpServer
không tự gọi vào sự kiện vòng/hệ thống ổ cắm theo dõi, nhưng nó phụ thuộc vào nó thông qua QSocketNotifier
mà nó sử dụng cho recieving không đồng bộ các kết nối.
Khi phương pháp đồng bộ waitForNewConnection()
được gọi là nó chỉ bỏ qua tất cả các công cụ QSocketNotifier
và gọi accept()
sẽ chặn luồng cho đến khi có kết nối đến.
Rất đẹp. Bây giờ tôi hiểu lý do tại sao gọi lắng nghe trước khi thực hiện các vòng lặp sự kiện ứng dụng trong Qt (tôi sử dụng PyQt) đã dẫn đến việc không nhận được một tín hiệu 'newConnection'. Cảm ơn bạn đã đào bới. – Trilarion