2012-07-26 21 views
8

Tôi quan tâm đến cách QTcpServer hoạt động sau hậu trường liên quan đến chủ đề và chặn. QTcpServer có phương thức listen() trả về ngay lập tức. Nếu nghe thành công, máy chủ sẽ phát ra tín hiệu newConnection(). Tôi quan tâm đến việc máy chủ lắng nghe như thế nào (nó có nằm trong chủ đề chính) khi phương thức listen() đã trở lại hay không. Ví dụ thông thường của một ứng dụng giao diện điều khiển với một QTcpServer là một cái gì đó như thế này:QTcpServer thực sự lắng nghe các kết nối như thế nào

//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 phụ thuộc vào một QCoreApplication (hoặc có thể là một QRunLoop) hiện có và chạy để recive sự kiện mạng. Nó có thể hoạt động đúng cách mà không cần gọi số QCoreApplication::exec() không?

Trả lời

16

Tôi đã khoan qua mã nguồn của các mô-đun QtCoreQtNetwork.

Aperantly, QTcpServer thể làm việc trong hai chế độ: đồng bộ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 QCoreApplicationQEventLoopQAbstractEventDispatcher (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.

+0

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

0

Hầu hết của Qt "đằng sau hậu trường" chức năng xảy ra bên trong vòng lặp sự kiện chính QCoreApplication của: tín hiệu/khe, giờ vv
Một ví dụ sẽ JavaScript - bạn ràng buộc một sự kiện, nhưng vòng lặp sự kiện được xử lý bởi trình duyệt.

Các vấn đề liên quan