문제

스레드 및 차단과 관련하여 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() 새로운 연결이 수락되면 신호를 보냅니다.그러나 이를 수행하려면 이벤트 루프가 실행되어야 합니다.기초 QCoreApplicationQEventLoop 그리고 QAbstractEventDispatcher (추상 클래스, 구체적인 유형은 OS에 따라 다릅니다. 예를 들어 QEventDispatcherUNIX).이 이벤트 디스패처는 소켓의 조건(파일 설명자로 표시됨)을 모니터링할 수 있습니다.방법이 있어요 registerSocketNotifier(QSocketNotifier*).이 메소드는 생성자에 의해 호출됩니다. QSocketNotifier 수업, 어느 QTcpServer 매번 인스턴스를 생성합니다. listen() 호출됩니다.호출되는 유일한 시스템 호출은 QTcpServer::listen() 호출되는 것은 물론입니다. listen() 즉시 반환되므로 이벤트 루프가 실행되기 시작하면 모든 실제 마법이 발생합니다.이벤트 루프(디스패처 사용)는 등록된 소켓에 특정 조건이 있는지 모니터링합니다.그것은 전화 select() 특정 조건(읽을 데이터가 있는 경우, 데이터를 쓸 수 있는 경우 또는 오류가 발생한 경우)에 대해 커널이 모니터링할 하나 이상의 파일 설명자를 수신하는 시스템 호출입니다.호출은 소켓의 조건이 충족될 때까지 스레드를 차단할 수 있거나 일정 시간이 경과하고 소켓의 조건이 충족되지 않은 후에 반환될 수 있습니다.Qt가 전화를 걸고 있는지 잘 모르겠습니다. select() 대기 시간을 제공하거나 제공하지 않거나(무기한 차단), 다소 복잡한 방식으로 결정되고 변경 가능하다고 생각합니다.따라서 마침내 소켓의 조건이 충족되면 이벤트 디스패처는 QSocketNotifier 해당 소켓에 대해 다음과 같이 알려줍니다. QTcpServer 소켓을 듣고 있는 사람은 연결을 수락하고 newConnection() 신호.


그래서 QTcpServer 자체적으로는 이벤트 루프/소켓 모니터링 시스템을 호출하지 않지만 다음을 통해 시스템에 의존합니다. QSocketNotifier 비동기 연결 수신에 사용됩니다.

동기식일 때 waitForNewConnection() 호출되어 모든 것을 우회합니다. QSocketNotifier 물건과 전화 accept() 들어오는 연결이 있을 때까지 스레드를 차단합니다.

다른 팁

QT의 "장면 뒤의"기능이 QCoreapplication의 주요 이벤트 루프 내부에서 발생합니다. 신호 / 슬롯, 타이머 등
예제는 JavaScript입니다. 이벤트를 바인딩하지만 이벤트 루프는 브라우저에서 처리됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top