我有一个服务器,它在一个单独的线程中处理每个客户端连接。为了测试它,我实现了一个简单的回声" service:我在客户端输入一条消息,然后发送到服务器,服务器将其发回,客户端显示它。
因为我只发送短数据包,所以我只使用一次写入和读取来进行当前测试,我从来没有任何拆分数据包。
客户端使用write()
和readAll()
,它始终完美运行(使用数据包嗅探工具验证)
我几乎一直在观察的是,服务器每隔一次只发送数据包。
例如:
write()
函数返回3. write()
函数返回3. 在极少数情况下,一条信息就足够了。但是,大多数情况下,需要第二条消息来发送第一条和第二条消息。
客户端调试输出的一个示例,指示发送和接收的内容(请注意,客户端发送的所有内容都是手动输入的,并且在每条消息之间等待至少10秒):
Client: 1
Client: 2
Server: 1
Server: 2
Client: 12345
Server: 12345
Client: abc
Client: def
Server: abcdef
Client: 123
Server: 123
Client: 456
Client: 789
Server: 456789
Client: a
Server: a
Client: b
Client: c
Server: b
Server: c
我知道TCP是一个连续的流,但我并不期望在没有负载的LAN上,传输几个字节需要几分钟。有趣的是,客户端可以正确地立即发送所有内容,它永远不会等待进一步的写入将它们粘合在一起。
由于客户似乎工作得很好,我怀疑我的线程出了问题。
一旦QTcpServer
收到传入连接,我就会启动一个新线程,将socketDescriptor传递给线程的构造函数。
TcpThread::TcpThread(int socketDescriptor, QObject *parent) : QThread(parent)
{
this->socketDescriptor = socketDescriptor;
}
void TcpThread::run()
{
if (!tcpSocket->setSocketDescriptor(socketDescriptor)) {
qDebug() << tcpSocket->error();
return;
}
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(read_data()));
while (tcpSocket->state() == QAbstractSocket::ConnectedState)
{
tcpSocket->waitForDisconnected(-1);
}
}
void TcpThread::read_data()
{
QByteArray data = tcpSocket->readAll();
int nr = tcpSocket->write(data);
qDebug() << data << " (" << nr << " bytes written)";
}
我知道,这不是处理线程的best practice,我只是使用&#34; Qt4方法&#34;快速熟悉QTcpSocket。
有趣的是,每次拨打write()
时都会收到警告:
QSocketNotifier:无法启用或禁用套接字通知程序 另一个线程
我想知道为什么。我在我的线程的QTcpSocket
方法中创建了一个run()
的实例,所以它应该在同一个帖子中,不应该吗?
实际上,如果我将套接字的实例化移动到构造函数,我得到
QObject:无法为不同的父级创建子级 线。 (Parent是QTcpSocket(0x2c54a80),父亲的线程是 QThread(0x10776d0),当前线程为TcpThread(0x2c53c18)
我之前没有得到过。但是,即使在构造函数中进行实例化,我的代码也完全相同:消息有时会立即发送,有时它会粘贴到下一条消息并与之一起发送,无论两者之间经过多长时间。
我做错了什么?
答案 0 :(得分:0)
使用QTcpSocket
毫无意义的线程。它是异步API,因此使用线程获得的收益很小(问题可能只有当你有其他耗时的工作阻止事件循环时)。
另一个问题是您创建对象并将其分配给线程的方式。你已经给出了关于这个主题的完美链接,但你完全不理解它。
在QT中使用线程时的简单规则:
QThread::run()
并使用信号和插槽时,您应该在该线程中运行事件循环,方法是调用QThread::exec()
或创建新的事件循环。所以一般来说,你的代码中有很多错误。我会重新放弃QThread
或至少阅读那篇文章再次理解并应用其建议(它是在Qt5发布之前编写的,所以你的主张“Qt4风格”无效)。