2012-07-26 2 views
8

스레드 및 차단과 관련하여 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) 기존 및 네트워크 이벤트를 받아 봐을 실행하십시오 QTcpServer와 콘솔 응용 프로그램의 일반적인 예는이 같은 것입니다. QCoreApplication::exec()이 호출되지 않으면 제대로 작동합니까?

답변

16

나는 QtCoreQtNetwork 모듈의 소스 코드를 시추 해왔다.

Aperantly, QTcpServer는 두 가지 모드로 작동 할 수 있습니다 동기비동기합니다. 동기 모드

차단 방법을 호출 할 수 waitForNewConnection()listen() 발신자를 호출 한 후 (누군가가 수신 포트에 연결될 때까지 스레드 잠 것이다). 이 방법은 QTcpServer 이벤트 루프없이 스레드에서 작동 할 수 있습니다.

모드 QTcpServer은 새로운 연결이 수락되었을 때 newConnection() 신호를 방출합니다. 하지만이 작업을 수행하려면 이벤트 루프를 실행해야합니다. QCoreApplication 밑에는 QEventLoopQAbstractEventDispatcher (추상 클래스, 콘크리트 유형은 OS에 따라 다릅니다 (예 : QEventDispatcherUNIX)입니다. 이 이벤트 디스패처는 소켓 (파일 설명자로 표시)에 대한 조건을 모니터링 할 수 있습니다. 메서드는 registerSocketNotifier(QSocketNotifier*)입니다. 이 메서드는 QSocketNotifier 클래스의 생성자에서 호출하며 QTcpServerlisten()이 호출 될 때마다 인스턴스를 만듭니다. QTcpServer::listen()이 호출 될 때 호출되는 유일한 시스템 호출은 물론 listen()입니다. 즉, 즉시 반환되는 모든 실제 마법은 이벤트 루프가 실행될 때 발생합니다. 이벤트 루프 (디스패처 사용)는 등록 된 소켓에 특정 조건이 있는지 모니터링합니다. select() 시스템 호출은 특정 조건 (커널이 읽을 수있는 데이터가 있거나 데이터를 쓸 수 있거나 오류가 발생한 경우)에 대해 모니터링 할 하나 이상의 파일 디스크립터를받습니다. 호출 조건은 소켓 조건이 충족 될 때까지 스레드를 차단하거나 일정 시간이 경과하고 소켓 조건이 충족되지 않으면 리턴 할 수 있습니다. Qt가 대기 시간이 제공되거나 제공되지 않고 (무한정으로 차단) select()으로 전화를 걸면 확실하지 않습니다. 복잡한 방법으로 변경 될 수 있다고 판단됩니다. 따라서 소켓의 상태가 마침내 충족되면 이벤트 디스패처는 QSocketNotifier에 해당 소켓을 알리고 소켓을 청취중인 사람 (QTcpServer)에게이를 알리고 연결을 수락하고 newConnection() 신호를 내 보냅니다.


는 그래서 QTcpServer는 이벤트 루프/소켓 모니터링 시스템으로 호출하지 자체 않지만, 그것은 연결의 비동기 잡에 사용하는 QSocketNotifier 통해에 따라 달라집니다.

동기 메서드 waitForNewConnection()을 호출하면 모든 QSocketNotifier 항목을 무시하고 들어오는 연결이있을 때까지 스레드를 차단하는 accept()을 호출합니다.

+0

아주 좋습니다. 이제 Qt에서 응용 프로그램 이벤트 루프를 실행하기 전에 (내가 PyQt를 사용하여) 'newConnection' 신호를받지 못하는 이유를 들어 보았습니다. 파고 주셔서 감사합니다. – Trilarion

0

Qt의 대부분의 기능은 QCoreApplication의 메인 이벤트 루프 (신호/슬롯, 타이머 등)에서 발생합니다.
예를 들어 JavaScript를 사용하면 이벤트를 바인딩하지만 이벤트 루프는 브라우저에서 처리됩니다.