Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt如何将有效的socketDescriptor传递给线程_C++_Multithreading_Qt_Sockets - Fatal编程技术网

C++ Qt如何将有效的socketDescriptor传递给线程

C++ Qt如何将有效的socketDescriptor传递给线程,c++,multithreading,qt,sockets,C++,Multithreading,Qt,Sockets,我正在尝试实现线程服务器应用程序,该应用程序在每个物理CPU核心/线程上运行1个处理线程。 目标是将所有传入连接分散到线程上,如果需要,线程必须关闭连接。 我的服务器实现基于qtcserver和重新实现incomingConnection功能,该功能检查所有底层线程的当前连接计数,并将qintptpr socketDescriptor传递给线程类函数,该函数仅将此qintptpr添加到“挂起会话”列表中。 在thread::run中,我有一个无限循环,这个循环检查“挂起的会话”列表,如果它不是空

我正在尝试实现线程服务器应用程序,该应用程序在每个物理CPU核心/线程上运行1个处理线程。 目标是将所有传入连接分散到线程上,如果需要,线程必须关闭连接。 我的服务器实现基于qtcserver和重新实现incomingConnection功能,该功能检查所有底层线程的当前连接计数,并将qintptpr socketDescriptor传递给线程类函数,该函数仅将此qintptpr添加到“挂起会话”列表中。 在thread::run中,我有一个无限循环,这个循环检查“挂起的会话”列表,如果它不是空的,则创建新的qtcsocket并将新创建的套接字对象的socketDescriptor传递给setSocketDescriptor函数。 我在控制台日志中看到了我传递的有效的socketDescriptor(与我在incomingConnection函数中的值相同),[错误信息,我在“if”语句中遗漏了“!”:但setSocketDescriptor失败,错误为“未知错误”]编辑:setSocketDescriptor函数成功,但套接字不接受任何数据,即使远程客户端关闭了连接,::socketDescriptor()返回最初传递的值(在“连接丢失”类型的情况后必须为-1)

问题是:在调用incomingConnection和线程的下一个循环之间,socketDescriptor到底发生了什么? 我发现许多示例中,socketDescriptor成功地传递给了线程对象的构造函数(因此,socketDescriptor在连接后立即被“使用”),但我需要在线程生命周期的后期创建套接字对象。 我可以在incomingConnection功能中正确设置QTcpSocket,它将正常工作。我将尝试这样做,并通过moveToThread()将QTcpSocket传递给所需的线程,但即使它可以工作,我还是想知道当前实现失败的原因

代码(主线程接受连接):

void服务器::incomingConnection(qintpttr socketDescriptor)
{

qDebug()我真的不知道在这种情况下,您需要什么“挂起的会话”

这是通过
incomingConnection()
qtcsocket
转发套接字描述符的可能方法之一。我们创建SocketThread对象,它继承QThread

void Server::incomingConnection(qintptr handle)
{
    SocketThread *thread = new SocketThread(handle);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    thread->start();
}
在contructro中,我们初始化私有成员m_socketDescriptor:

SocketThread::SocketThread(qintptr descriptor, QObject *parent)
    : QThread(parent),
      m_socketDescriptor(descriptor)
{

}
如果我们继承
QThread
类,那么我们必须重写
run()
方法

void SocketThread::run()
{
    m_socket = new QTcpSocket;
    m_socket->setSocketDescriptor(m_socketDescriptor);

    connect(m_socket, SIGNAL(readyRead()),    this, SLOT(onReadyRead()),    Qt::DirectConnection);
    connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()), Qt::DirectConnection);

    exec();
}
在运行时,您可以看到我们初始化
qtcsocket
,设置套接字描述符,连接
readyRead()
disconnected()
信号与相关插槽并启动事件循环

readyRead()
处,我们从套接字读取数据,然后断开与主机的连接:

void SocketThread::onReadyRead()
{
    // get data from socket
    m_socket->disconnectFromHost();
}
onDisconnected()
上,只需关闭套接字并退出事件循环:

void SocketThread::onDisconnected()
{
    m_socket->close();
    quit();
}
这是可能的方法之一


我希望您能够根据您的项目调整我的代码。向您致意

谢谢您的回复!但正如我之前所说的:我发现了许多示例,其中socketDescriptor成功地传递给Thread对象的构造函数(因此socketDescriptor在连接后立即“使用”),但我需要在线程生命周期的后期创建套接字对象。我不希望每个连接有1个线程。我需要每个CPU有1个线程(实际处理线程).目前,我重新实现了所有功能,以便在主线程中创建QTcpSocket对象并将其传递给工作线程。它的工作方式与我在最初的帖子中所预期的一样。但我仍然不明白我的第一次尝试有什么问题。哦,好的,对不起。您是否需要查看QThreadPool?另外,我现在只在代码
部分看到它,如果(!newsocket.setSocketDescriptor(sd))
但是您有指向QTcpSocket的指针,所以请使用->运算符。是的,我在尝试制作代码的简短版本时犯了一个错误。谢谢,现在已修复。我不知道QThreadPool在这里可以帮到我什么。它可以帮助管理许多线程,但我认为为每个连接创建单个线程是不合理的(我可以同时拥有超过10k的连接)。目前我的解决方案是在主线程中进行网络IO,但在工作线程中进行数据包加密/解密、解析和决策(针对每个会话)(每个CPU核1个)。我也在第一篇帖子中添加了一些评论。感谢大家的参与!如果有人感兴趣的话。我放弃了将其付诸实践并从0重新实现网络的尝试。在新的实现中,我在主线程中有QTcpServer,它接受连接,分配QTcpSocket对象并调用setSocketDescriptor。但我从分离的工作线程(将套接字对象传递给决策单元,决策单元存在于QThread的上下文中).由于读/写调用来自其他线程,我假设任何数量的CPU核都可以正常工作…但不能绝对确定atm。当我需要删除套接字时,我稍后只调用delete。新解决方案的问题是所有网络输出都必须从主线程(分配服务器和套接字)完成。我可以从工作线程中读取套接字,但不能写入。谷歌告诉我Qt IO设计的局限性。我不知道如何解决这个问题,只能希望用W线程做所有决策并从M线程发送数据包可以。可能有点晚了,但我试着做了类似的事情。你是否尝试在中设置工作线程一个QThread,并将
QMetaObject::invokeMethod()
Qt::QueuedConnection
一起使用?
void SocketThread::run()
{
    m_socket = new QTcpSocket;
    m_socket->setSocketDescriptor(m_socketDescriptor);

    connect(m_socket, SIGNAL(readyRead()),    this, SLOT(onReadyRead()),    Qt::DirectConnection);
    connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()), Qt::DirectConnection);

    exec();
}
void SocketThread::onReadyRead()
{
    // get data from socket
    m_socket->disconnectFromHost();
}
void SocketThread::onDisconnected()
{
    m_socket->close();
    quit();
}