首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将有效的socketDescriptor传递给线程

如何将有效的socketDescriptor传递给线程
EN

Stack Overflow用户
提问于 2015-05-20 18:57:28
回答 1查看 2.5K关注 0票数 1

我试图实现线程服务器应用程序,它运行每个物理CPU核心/线程一个处理线程。目标是将所有传入连接分散到线程上,如果需要的话,线程必须关闭连接。我的服务器实现基于QTcpServer并重新实现了QTcpServer功能,它检查所有底层线程的当前连接计数,并将qintptr socketDescriptor传递给线程类函数,后者只将此qintptr添加到“挂起会话”列表中。在socketDescriptor线程::runi有无穷循环中,这个循环检查“挂起会话”的列表,如果不是空的话-创建新的QTcpSocket并将传递给新创建的套接字对象的setSocketDescriptor函数。我在控制台日志中看到了我传递有效socketDescriptor的内容(与incomingConnection函数中的值相同),错误的信息,我只是错过了“!在我的" if“语句中:但是setSocketDescriptor函数失败了,但::socketDescriptor()函数失败了,但是套接字不接受任何数据,即使远程客户端关闭了连接,::socketDescriptor()也会返回最初传递的值(必须在”连接丢失“类型之后返回-1 )。

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

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

代码语言:javascript
复制
void Server::incomingConnection(qintptr socketDescriptor)

{
    qDebug()<<Q_FUNC_INFO<<"sd:"<<socketDescriptor;

    ServerThread* t = threads[0];

    // find thread with lowest connection count
    for (unsigned int i = 1; i < CPU_Count; i++)
    {
        if (threads[i]->getConnectionCount() < t->getConnectionCount())
            t = threads[i];
    }

    t->newConnection(socketDescriptor);
}

代码(将socketDescriptor传递给Thread对象以供进一步使用):

代码语言:javascript
复制
void ServerThread::newConnection(qintptr socketDescriptor)
{
// QList<qintptr> sessions_pending;
    sessions_pending.append(socketDescriptor);
}

代码(试图在ServerThread::run中创建QTcpSocket ):

代码语言:javascript
复制
    if (sessions_pending.count())
    {
        foreach (qintptr sd, sessions_pending)
        {
            qDebug()<<"create socket, descriptor : "<<sd; // show same value as incomingConnection

            QTcpSocket* newSocket = new QTcpSocket(0);
            if (!newsocket->setSocketDescriptor(sd))
                qDebug()<<"Error during socket creation : "<<s->socket->errorString()<<s->socket->error();
            // output: "Unknown error" QAbstractSocket::UnknownSocketError

            // .. here was code which store QTcpSocket and so on ..
        }
        sessions_pending.clear();
    }
EN

回答 1

Stack Overflow用户

发布于 2015-05-21 10:15:48

在这种情况下,我真的不知道你需要什么“待定会话”。

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

代码语言:javascript
复制
void Server::incomingConnection(qintptr handle)
{
    SocketThread *thread = new SocketThread(handle);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    thread->start();
}

在构造中,我们初始化私有成员m_socketDescriptor:

代码语言:javascript
复制
SocketThread::SocketThread(qintptr descriptor, QObject *parent)
    : QThread(parent),
      m_socketDescriptor(descriptor)
{

}

如果继承QThread类,则必须重写run()方法。

代码语言:javascript
复制
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();
}

在运行时,如您所见,我们可以插入QTcpSocket,设置套接字描述符,将readyRead()disconected()信号与相关插槽连接起来,并启动事件循环。

readyRead(),我们从套接字读取数据,然后从主机读取数据:

代码语言:javascript
复制
void SocketThread::onReadyRead()
{
    // get data from socket
    m_socket->disconnectFromHost();
}

onDisconnected(),只需关闭套接字并离开事件循环:

代码语言:javascript
复制
void SocketThread::onDisconnected()
{
    m_socket->close();
    quit();
}

这是可能的方法之一。

我希望你能使我的代码适应你的项目。诚挚的问候

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30358182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档