繁体   English   中英

如何使用Qt阻止tcp套接字?

[英]How to make blocking tcp socket with Qt?

我使用QTcpSocket 我需要对套接字进行任何写/读调用以使其同步(阻塞)。

我知道有waitForReadyRead()waitForBytesWritten() ,但是Qt文档中标记了这两种方法,因为它们在Windows下可能会随机失败。 我不能为此。

阻塞读取是最重要的(因为读取总是在向另一个对等方写入命令之后进行的,所以我知道如果数据到达另一个对等方,它将回答)。

我尝试了2种方法。

第一:

QByteArray readBytes(qint64 count)
{
    int sleepIterations = 0;
    QByteArray resultBytes;
    while (resultBytes.size() < count && sleepIterations < 100)
    {
        if (socket->bytesAvailable() == 0)
        {
            sleepIterations++;
            QThread::msleep(100);
            QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
            continue;
        }

        resultBytes += socket->read(qMin(count, socket->bytesAvailable()));
    }
    return resultBytes;
}

这应该等待字节可用于在套接字上读取,同时处理事件循环,因此套接字正在做必要的内部工作。

不幸的是-出于我未知的原因bytesAvailable()有时返回正确的字节数,但有时却永远不会返回大于0的任何值。

我实际上知道要读取数据,因为它曾经与第二种方法一起工作(但它有其自身的问题)。

第二:

我有一种信号“阻止程序”,它阻止当前上下文并处理事件循环,直到发出某些信号为止。 这是“阻止者”:

SignalWait.h:

class SignalWait : public QObject
{
        Q_OBJECT

    public:
        SignalWait(QObject *object, const char *signal);

        bool wait(int msTimeout);

    private:
        bool called = false;

    private slots:
        void handleSignal();
};

SignalWait.cpp:

SignalWait::SignalWait(QObject* object, const char* signal) :
    QObject()
{
    connect(object, signal, this, SLOT(handleSignal()));
}

bool SignalWait::wait(int msTimeout)
{
    QTime timer(0, 0, 0, msTimeout);
    timer.start();
    while (!called && timer.elapsed() < msTimeout)
        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);

    return called;
}

void SignalWait::handleSignal()
{
    called = true;
}

然后我像这样使用它:

SignalWait signalWait(socket, SIGNAL(readyRead()));
// ...
// socket->write(...);
// ...
if (!signalWait.wait(30000))
{
    // error
    return;
}
bytes = socket->read(size);

这种方法似乎效果更好,但有时也会失败。 我不知道为什么 就像readyRead()信号从未发出过, SignalWait一直等待直到超时。

我没主意了。 处理它的正确方法是什么?

我建议使用异步方法,但是如果您真的想使用同步方法,那么更好的方法是使用本地事件循环:

QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
loop.connect(socket, SIGNAL(readyRead()), SLOT(quit())); 
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));

while (resultBytes.size() < count)
{
    timer.start(msTimeout);
    loop.exec();

    if(timer.isActive())
        resultBytes += socket->read(qMin(count, socket->bytesAvailable()));
    else
        break;
}

在这里,它等待直到读取count字节或达到超时为止。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM