从QTcpSocket读取数据的问题

时间:2011-08-15 22:21:03

标签: c++ sockets qt4 client

我从Qt示例中修改了threaded fortune-server。 客户端连接到服务器,然后发送标头进行身份验证。

tcpSocket = new QTcpSocket();
tcpSocket->connectToHost(addr, port);
QByteArray block = "someheader";
int x = tcpSocket->write(block);
qDebug() << x;

此处客户端似乎正常,qDebug会打印block的实际大小。

在服务器端,我已经预定义了incomingConnection,并且我开始了每个新连接的线程。

void Server::incomingConnection(int socketDescriptor) {
    const QString &str = vec[qrand() % vec.size()];
    SpellThread *thread = new SpellThread(socketDescriptor, str);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    qDebug() << " -- incoming connection";
    thread->start();
}

我正在连接sock以检查是否有东西要读。 (sock此处为QTcpServer*

void SpellThread::run() {
    qDebug() << " -- in spellthread";
    connect(sock, SIGNAL(readyRead()), this, SLOT(checkBytes()));
    //....
    qDebug() << " -- end spellthread";
}

第一个问题是,当我从客户端发送数据时,readyRead不会被触发。 (我在checkBytes中添加了调试消息) 消息是:

 -- incoming connection 
 -- in spellthread 
 -- end spellthread

虽然客户端打印标题长度的实际大小。

第二个问题是checkBytes目前的设计非常糟糕。首先它检查是标题OK并设置一个标志,然后它获取消息的大小并设置另一个标志,最后它获得真实的消息。这非常笨拙。我首先试图逃避信号,而是使用sock->waitForReadyRead()。但是它总是返回false。 (来自文档:“重新实现此功能,为自定义设备提供阻止API。默认实现不执行任何操作,并返回false。”)。

那么如何在Qt中实现具有多个客户端和多个读/写的客户端/服务器应用程序?我真的想要改进应用程序设计的建议,并解决我目前的两个问题。

1 个答案:

答案 0 :(得分:2)

如果没有调用QThread::exec()来启动该线程/运行函数中的事件循环,则不能在线程中使用插槽或套接字信号。

由于你的checkBytes插槽属于QThread,因此线程不会执行(有关于QThreads here的详细文章)

最接近你想要的例子是Network Chat(特别是两个班级ServerConnection)。

----------
修改
如果需要使用线程(没有任何插槽),QTcpSocket对象必须属于与您调用waitForReadyRead的线程相同的线程。例如,使用:

SpellThread::SpellThread(int socketDescriptor, const QString & str) {
    tcpSocket = new QTcpSocket(); // There should be no parent to be able
                                  // to move it to the thread
    tcpSocket->moveToThread(this);
    ...

或者通过在QTcpSocket函数中创建run对象,使其自动属于该线程(在财富示例中对其进行了简要说明)。 如果您动态分配QTcpSocket,并且因为它没有父代,您也应该手动删除它。