QTcpSocket - problema con utilizzo contemporaneo del write e read



  • Ho la seguente necessità:

    1. inviare una frame ad un dispositivo remoto
    2. verificare che la frame sia stata trasmessa
    3. attendere la frame di risposta dal dispositivo remoto
      Tra la trasmissione della frame e la ricezione della frame di risposta intercorrono alcune decine di msec.
      Ho provato diverse soluzioni ottenendo i seguenti risultati:
      a) la frame viene inviata al dispositivo remoto ma il chiamante sembra non ricevere la frame di risposta
      b) il chiamante non invia la frame al dispositivo remoto.

    Ho collegato il signal readyRead alla funzione che deve scodare la frame ricevuta:
    connect(tcpSocket, &QIODevice::readyRead, this, &networkReadData);
    ed ho verificato che il meccanismo funziona correttamente.

    Se dal chiamante provvedo ad invocare la funzione per la scrittura della frame sul socket:
    tcpSocket->write(frame);
    while( tcpSocket->bytesToWrite() > 0 )
    {
    if ( !tcpSocket->waitForBytesWritten(1000) )
    {
    txErrorCode = -99997;
    return false;
    }
    }
    verifico che la frame è stata inviata, analizzo tramite WireShark che il dispositivo remoto ha trasmesso la risposta ma il signal "readyTìRead" non viene inviato.

    Se effettuo la sola scrittura tramite "tcpSocket->write(frame);" e non attendo che la frame sia stata completamente inviata, alla ricezione della frame il signal viene inviato.

    Ho quindi pensato di sincronizzare il meccanismo inserendo un flag che viene settato a ricezione ultimata ed un timer come watchdog::
    receivedFrame = false;
    timeoutOccurred = false;
    tcpSocket->write(frame);
    watchdogTimer->start(); // watchdogTimer= new QTimer(this);
    while ( (timeoutOccurred == false) && (receivedFrame==false));

    In questo caso ottengo che la frame non viene inviata verso il dispositivo remoto ed il timer non scatta....., come se il while(); di attesa bloccasse la gestione degli eventi.....



  • Il codice postato non e' sufficiente per determinare da dove arrivi il problema. Quasi sempre il "readyRead non viene inviato" e' dovuto al fatto che o non hai un event loop o lo stai ploccando (con un while(true) o cose simili). Non e' necessario usare while( tcpSocket->bytesToWrite() > 0 ) ne waitFor*() e la maggior parte delle volte e' dannoso



  • Temo che sia come dici in quanto la sequenza da me adottata è sequenziale e bloccante:

    1. da interfaccia grafica premo un bottone che tramite CALL invoca la trasmissione di una frame
    2. la funzione identifica quale frame deve trasmettere, ne prepara il corpo e poi invoca, anch'essa tramite CALL, la funzione che si occupa di completare la frame e della trasmissione fisica
    3. la trasmissione avviene come funzione tradizionale che invia la frame sul socket, attiva il timer di watchdog come singleshot e poi rientra
    4. quando rientro nella funzione del punto (2), tramite:
      while ( (timeoutOccurred == false) && (receivedFrame==false));
      attendo che il timer sia scattato (la funzione di servizio collegata allo SLOT imposta timeoutOccurred = true, oppure che la frame di ricezione sia stata ricevuta..........

    Mi potresti cortesemente inviare un esempio dell' "event loop" oppure indicare dove poter guardare?
    Grazie.



  • Non e' un esempio completo ma ci sono tutti i pezzi necessari: https://github.com/VSRonin/ChatExample



  • Ti sono veramente grato, grazie.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.