我对 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() 被召唤?

有帮助吗?

解决方案

我一直在研究源代码 QtCoreQtNetwork 模块。

顺便说一下, QTcpServer 可以在两种模式下工作: 同步异步.

同步 通话后模式 listen() 呼叫者可以呼叫 waitForNewConnection() 这是一种阻塞方法(线程将休眠,直到有人连接到侦听端口)。这边走 QTcpServer 可以在没有事件循环的线程中工作。

异步 模式 QTcpServer 将发出 newConnection() 当接受新连接时发出信号。但为了能够做到这一点,必须运行一个事件循环。底层的 QCoreApplicationQEventLoopQAbstractEventDispatcher (抽象类,具体类型取决于操作系统,例如 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