使用Qt编写跨平台应用程序(包括带MinGW的Windows)。为了从SSL套接字读取数据,我正在创建一个单独的线程。这个帖子是出于历史原因,因为之前的应用程序是使用C socket / ssl / crypto库编写的。现在所有这些都被Qt网络库取代。
对于阻止线程,waitForReadyRead(milliseconds)
似乎是更好的选择。现在根据Qt层次结构:
QIODevice
|
QAbstractSocket
|
QTcpSocket
|
QSslSocket
QAbscractSocket::waitForReadyRead()
的文档建议:
注意:此功能可能在Windows上随机失败。如果您的软件将在Windows上运行,请考虑使用事件循环和readyRead()信号。
但是QIODevice::waitForReadyRead()
中没有提到类似的警告。
问题:QSslSocket::waitForReadyRead()
是否始终可用于所有平台?
为什么我没有使用readyRead()信号?
由于一些奇怪的原因,如果我用readyRead()插入一些方法,那么它就不会被调用。而且,QSslSocket :: write()也不起作用,否则与上述方法一起工作。由于我的代码很复杂,我无法在此处提供。
答案 0 :(得分:5)
对于您的问题:是的,您可以使用QSslSocket::waitForReadyRead()
但是在Widows上,即使数据进入套接字,它也可以超时。因此,如果发生超时,您必须检查它是否超时或方法失败。如果QAbstractSocket::bytesAvailable() > 0
然后数据准备好读取,则检查很简单,否则它会超时。
当您使用小超时并且您的应用程序对延迟不敏感时(例如温度传感器和具有温度历史记录的云之间的通信),这种方法是可行的。但是如果您不接受任何不必要的延迟,那么您应该使用信号/插槽接口。
有关详细信息,请查看Qt错误跟踪器上的bug report。
答案 1 :(得分:1)
根据你的问题。 QIODevice的实现只会返回false。因此,没有必要提示有时会失败。 QAbstractSocket的实现在内部调用称为“nativeSelect”的东西,然后根据您运行的操作系统将其定向到相应的方法。对于Windows,select实现有时似乎返回负false。 但这不应该伤害你,因为你应该从下次调用waitForReadyRead()获得可用数据的提示。 QSslSocket的waitForReadyRead()internaly使用QAbstactSocket的一些SSL检查实现appart。
关于信号和插槽的问题。 我刚接触Qt时犯的错误是,在我通过调用QApplication :: exec()或其他东西启动MainLoop之前,我试图发出信号。 没有运行循环,信号插槽机制不起作用。
希望你能从中获得一些提示。
此致
答案 2 :(得分:1)
问题可能是使用资源。
当您使用waitForReady*
时,每个线程创建约束一个套接字(否则您将遇到奇怪的错误)。
现在问题是你有多少个插座?如果它取决于运行时数据,您可能不知道。
一些嵌入式系统对可能影响您的应用程序的踏板数量有限制,IMO这只是可能影响此类实施的限制。
这部分问题:
为什么我不使用readyRead()信号?出于一些奇怪的原因,如果我 使用readyRead()插入一些方法,然后它就不会被调用。 而且,QSslSocket :: write()也不起作用,这是有效的 否则采用上述方法。由于我的代码很复杂,我是 无法在这里展示。
看起来很可疑 我从未见过有人遇到类似的问题。也许代码的某些部分阻止了事件循环?
答案 3 :(得分:0)
虽然这不是Qn的确切答案,但我发布了class MySslSocket : QSslSocket
{
Q_OBJECT
public:
virtual
bool
waitForReadyRead (int milliseconds) override final
{
QEventLoop eventLoop;
QTimer timer;
connect(this, SIGNAL(readyRead()), &eventLoop, SLOT(quit()));
connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
timer.setSingleShot(true);
timer.start(milliseconds);
eventLoop.exec();
return timer.isActive();
}
};
的可能实现,可以在本地事件循环中使用。
$this->Model->saveAll(array_of_30000_rows);
这可以专门用于Windows,也可以用于所有平台。