LINUX.ORG.RU

QTcpSocket как узнать о том, что пора читать?

 


0

1
socket.write("COMMAND");
socket.waitForBytesWritten();
QThread::msleep(100); //магия
socket.waitForReadyRead(-1);
how_many = socket.read(buffer, sizeof(buffer));

работает. без «магической» строчки — не работает (якобы ничего не приходит в порт)

...
connect(&socket, SIGNAL(readyRead()), this, SLOT(read());
socket.write("COMMAND");
socket.waitForBytesWritten();
while(wrote_smth < 1);
...


public slots: 
void read(){
  qDebug()<<"start read\n";
  wrote_smth = socket.read(buffer, sizeof(buffer));
}

тоже не работает. что-то не так делаю? «start read» не пишет.

★★★★★

Последнее исправление: next_time (всего исправлений: 1)

Ответ: readyRead(). Неясно у вас в коде socket это указатель или значение. Он точно не удаляется раньше времени? Главный цикл событий запускается?

Dendy ★★★★★
()

waitForBytesWritten()
This function blocks until at least one byte has been written on the socket

т.е. был вызван send(), что не гарантирует доставку, а всего лишь копирует данные в буфер операционной системы (доставка будет произведена позднее, если возможно).

waitForReadyRead(-1)

-1 не документировано, возможно для сокета работает как немедленный возврат

Во втором случае while() блокирует завершение метода, в результате метод read() стоит в очереди, но так и не вызывается.

anonymous
()
Ответ на: комментарий от Dendy

socket.
Неясно у вас в коде socket это указатель или значение.

э?

Он точно не удаляется раньше времени?

это переменная, принадлежащая классу, очевидно же

Главный цикл событий запускается?

кхм...

next_time ★★★★★
() автор топика
Ответ на: комментарий от anonymous

т.е. был вызван send(), что не гарантирует доставку, а всего лишь копирует данные в буфер операционной системы (доставка будет произведена позднее, если возможно).

ок, но запись-то как раз происходит, здесь всё нормально

-1 не документировано,

вполне себе документировано — бесконечное ожидание

next_time ★★★★★
() автор топика

каст kuzulis — c серийным портом на qt тоже самое, это видимо баг(фича?) корневого класса, от которого QTcpSocket и QSerialPort оба наследуют

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

bool QAbstractSocket::​waitForReadyRead(int msecs = 30000)

Reimplemented from QIODevice::waitForReadyRead().

This function blocks until new data is available for reading and the readyRead() signal has been emitted. The function will timeout after msecs milliseconds; the default timeout is 30000 milliseconds.

The function returns true if the readyRead() signal is emitted and there is new data available for reading; otherwise it returns false (if an error occurred or the operation timed out).

Note: This function may fail randomly on Windows. Consider using the event loop and the readyRead() signal if your software will run on Windows.

http://doc.qt.io/qt-5/qabstractsocket.html#waitForReadyRead

anonymous
()
Ответ на: комментарий от next_time

ок, но запись-то как раз происходит, здесь всё нормально

происходит, но код

socket.waitForReadyRead(-1); how_many = socket.read(buffer, sizeof(buffer));

выполняется раньше. Потому и работает при 100мс задержке.

anonymous
()
Client::Client(QTcpSocket *sock)
{
    this->sock = sock;
    sock->setParent(NULL);
    connect(sock,&QTcpSocket::disconnected,this,&Client::disc,Qt::QueuedConnection);
    readFromSock = connect(sock,&QTcpSocket::readyRead,this,&Client::readMessage,Qt::QueuedConnection);
    ...
    QMetaObject::invokeMethod(this,"readMessage",Qt::QueuedConnection);// Между соединением и установкой обработчика входящих данных проходит время, 
    //поэтому нужно вызвать один раз readMessage принудительно чтобы убедиться что в буфере сокета не лежит сообщение на которое клиент ожидает ответ.
}

void Client::readMessage()
{
    while(sock->bytesAvailable() != 0)
    {
        rxMess.append(sock->readAll());
    }
    parseMessage();
}
void Client::parseMessage()
{
    if(rxMess.size() == 0) return;
    //--------------------------data---------------------
    ...
    emit parseDone();
}

someResult Client::writeSomeDataAndProcessAnswer()
{
    sock.write("COMMAND");
    loop = new QEventLoop();
    connect(this,&Client::parseDone,loop,&QEventLoop::quit,Qt::QueuedConnection);
    loop->exec();
    delete loop;
    ...
    return someResult;
}
anonymous
()
Ответ на: комментарий от anonymous

bool QIODevice::​waitForReadyRead(int msecs)

Blocks until new data is available for reading and the readyRead() signal has been emitted, or until msecs milliseconds have passed. If msecs is -1, this function will not time out.

Returns true if new data is available for reading; otherwise returns false (if the operation timed out or if an error occurred).

This function can operate without an event loop. It is useful when writing non-GUI applications and when performing I/O operations in a non-GUI thread.

If called from within a slot connected to the readyRead() signal, readyRead() will not be reemitted.

Reimplement this function to provide a blocking API for a custom device. The default implementation does nothing, and returns false.

Warning: Calling this function from the main (GUI) thread might cause your user interface to freeze.

anonymous
()
Ответ на: комментарий от anonymous

c того что waitForBytesWritten() не значит что байты уже на другой стороне. Это значит что хотя бы один байт был передан системе с помощью нативного сокета. Дальше уже все во власти tcp стека, драйверов, физической задержки, маршрутизации и т.д.

anonymous
()
Ответ на: комментарий от anonymous

ОС, которая едва-едва способна за 300 миллисекунд передать по 100-мегабитной сетке пару байт. великолепно.

anonymous
()
Ответ на: комментарий от anonymous

Это значит что хотя бы один байт был передан системе с помощью нативного сокета. Дальше уже все во власти tcp стека, драйверов, физической задержки, маршрутизации и т.д.

и чё? waitForBytesWritten() уже завершился и настала очередь исполняться waitForReadyReading(), который обязан ждать прихода полезных данных, а что там отправлено и с какими задержками ему должно быть чихать.

anonymous
()

Выход один - желательно не использовать waitForXX(), избегать это вообще. Там внутри с реализацией этих waitForXX много мороки и прочей шняги, что приводит к багам в них. В общем, ненадежное все это.. Лучше *всегда* использовать сигналы/слоты и будет счастье. Я не понимаю, нафига вообще они эти методы ввели в QIODevice для асинхронного фреймфорка!!!, которые ни к селу ни к городу.. ИМХО, без них было-бы надежнее и проще.

kuzulis ★★
()
Ответ на: комментарий от kuzulis

Я не понимаю, нафига вообще они эти методы ввели в QIODevice для асинхронного фреймфорка!!!

у меня работа исключительно синхронная, при том приложение консольное и ему позволительно блокировать поток. поэтому, в целях простоты мне желательно обойтись именно waitForXX(). впрочем я уже переписал так как советовал анонимус: QTcpSocket как узнать о том, что пора читать? (комментарий)

и оно теряет первые байты, отправляемые устройством в ответ на запрос с компа.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

грубо говоря, если в ответ устройство отправляет «12345», мне приходит «345». причём, количество теряемых байт не постоянно.

next_time ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.