我试图实现线程服务器应用程序,它运行每个物理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传递到所需的线程,但即使它工作正常,我也想知道为什么我当前的实现失败了。
代码(主线程接受连接):
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对象以供进一步使用):
void ServerThread::newConnection(qintptr socketDescriptor)
{
// QList<qintptr> sessions_pending;
sessions_pending.append(socketDescriptor);
}代码(试图在ServerThread::run中创建QTcpSocket ):
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();
}发布于 2015-05-21 10:15:48
在这种情况下,我真的不知道你需要什么“待定会话”。
这是通过incomingConnection()和QTcpSocket转发套接字描述符的可能方法之一。我们创建SocketThread对象,它继承了QThread
void Server::incomingConnection(qintptr handle)
{
SocketThread *thread = new SocketThread(handle);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}在构造中,我们初始化私有成员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();
}在运行时,如您所见,我们可以插入QTcpSocket,设置套接字描述符,将readyRead()和disconected()信号与相关插槽连接起来,并启动事件循环。
在readyRead(),我们从套接字读取数据,然后从主机读取数据:
void SocketThread::onReadyRead()
{
// get data from socket
m_socket->disconnectFromHost();
}在onDisconnected(),只需关闭套接字并离开事件循环:
void SocketThread::onDisconnected()
{
m_socket->close();
quit();
}这是可能的方法之一。
我希望你能使我的代码适应你的项目。诚挚的问候
https://stackoverflow.com/questions/30358182
复制相似问题