Comunicare via TCP e leggere dati di una Struct



  • Ho il seguente problema,
    sono collegato ad un device che in linguaggio C crea un server TCP il quale risponde ai messaggi del client inviando una struttura con dei dati. Il server è questo:

    typedef struct
    {
       long quota1;
       long quota2;
       long flags;
       long progressivo;
    }DATI;
     
    //----------------------------------------------
    // server tcp port 5000
    //----------------------------------------------
    void task5000(void)
    {
       static int i5000=0;      //n. servers aperti contemporaneamente
       FILE *f=0;               //connessione TCP  (tipo ETH_FILE)
       char buffer[100];        //buffer ricezione dati
       DATI dati;               //dati da inviare al client
       int nbytes;              //n. di bytes arrivati dal client 
       if (i5000 < 3)           //accetta al massimo 4 clients contemporanei
       {
          f=fopen("TCP:SERVER",5000);  //open server porta 5000 
          if(f)                        //se connessione TCP avvenuta ...
          {
             i5000++;              //incrementa n. connessioni aperte
             MB1=i5000;            //led 
             while(!eof(f))        //fino a quando connessione attiva ...
             {
                if(nbytes=fread(buffer,80,1,f))     //se vi sono dati dal client li legge e ...
                {
                   dati.quota1=touch_x;             //prepara risposta
                   dati.quota2=touch_y;    
                   dati.flags=touch_premuto;
                   dati.progressivo++;
                   fwrite(&dati,sizeof(dati),1,f);  //invia risposta al client
                }
             }
             fclose(f);                 //a fine connessione chiude connessione
             i5000--;                   //decrementa n. connessioni attive
          }
       }
       MB1=i5000;                    //led 
       remove_task(THIS_TASK);       //chiude il task del server tcp
       while(1);                     //attende chiusura
    }
    

    Il mio client QT stabilisce la connessione e riceve i dati ma non so in che maniera trattare (leggere)i dati della struttura. Avete qualche consiglio / guida da darmi?

    Client

    
    TCPClientGui::TCPClientGui(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::TCPClientGui)
    {
        ui->setupUi(this);
        socket=new QTcpSocket(this);
        ui->port->setRange(0,9999);
        ui->port->setValue(5000);
        ui->trace->setReadOnly(true);
    
        connect(socket, SIGNAL(connected()), this, SLOT(connected()));
        connect(socket, SIGNAL(readyRead()), this, SLOT(readServer()));
    }
    
    TCPClientGui::~TCPClientGui()
    {
        delete ui;
    }
    
    void TCPClientGui::connectToHost(){
        socket->connectToHost(QHostAddress(ui->host->text()), ui->port->value());
    }
    
    void TCPClientGui::connected(){
        socket->write(QString("Hello Server").toLatin1());
        ui->trace->append("Connected");
        socket->waitForBytesWritten();
    }
    
    void TCPClientGui::sendMessage(){
        socket->write(QString(ui->message->text()).toLatin1());
        ui->trace->append("Ho inviato il messaggio");
        socket->waitForBytesWritten();
    }
    
    void TCPClientGui::readServer(){
        ui->trace->append(socket->readAll());
        qDebug() << "Ho letto: " << socket->readAll().toHex();
    }
    
    void TCPClientGui::on_sendMessage_clicked()
    {
         this->sendMessage();
    }
    
    void TCPClientGui::on_control_clicked()
    {
        this->connectToHost();
    }
    
    


  • Non ho modo di provarla ma questo dovrebbe andare.

    typedef struct
    {
       long quota1;
       long quota2;
       long flags;
       long progressivo;
    }DATI;
    void TCPClientGui::readServer(){
    while(socket->bytesAvailable() >= sizeof(DATI)){
    const QByteArray raw = socket->read(sizeof(DATI));
    const DATI* const rawData = reinterpret_cast<const DATI*>(raw.constData());
    qDebug() << rawData->quota1 << rawData->quota2<< rawData->flags << rawData->progressivo;
    }
    }
    

    NOTA: se server e client sono compilati con compilatori diversi e/o girano su sistemi diversi il tutto potrebbe andare a schifio in quanto sizeof(DATI) potrebbe essere diverso. Il server non e' fatto granche' bene ma suppongo tu non possa farci nulla

    Edit: aggiunti const mancanti



  • @VRonin Grazie mille Ronin , proverò la tua soluzione.
    Si purtroppo per il server non posso farci nulla, mi è stato consegnato così.

    Anche la tua Nota è corretta.. Vediamo cosa salta fuori!



  • Perfetto funziona, ho solo dovuto sistemare il cast
    DATI* rawData = const_cast<DATI*>(reinterpret_cast<const DATI*>(raw.constData()));



  • io eviterei const_cast dovrebbe essere l'ultima risorsa e qui hai alternative.

    basta dichiarare const DATI* rawData invece di DATI* rawData



  • @VRonin Ho un'ulteriore domanda sempre sull'esempio precedente.
    Vorrei testare la possibilità che la connessione cada.

    Per fare questo ho fatto così nel ciclo di ascolto:

    bool connected=false;
    while(1){
            //Se la connessione esiste invio il messaggio
            connected = (socket->state() == QTcpSocket::ConnectedState);
            if(connected){
                //Invio un messaggio di "polling" per ricevere le coordinate dal server
                sendMessage();
                delay(250);
                //La connessione non esiste/è caduta, la ripristino
            }else{
               qDebug() << "Stato diverso: abort ";
               socket->abort();
               socket->connectToHost(QHostAddress("192.168.0.12"), 5000);
           }
        }
    

    Ovviamente mi va a rifinire sempre nell'else ma non ho capito perchè dato che se elimino il controllo la connessione va che è una meraviglia e i messaggi vanno e vengono tranquillamente.

    Che cosa non ho capito di questo comando? socket->state() == QTcpSocket::ConnectedState

    Grazie

    EDIT: Mi rispondo da solo. Il delay troppo basso.



  • molto probabilmente e' perche' QTcpSocket e' in QTcpSocket::BoundState comunque puoi semplicemente connetere uno slot a disconnected ivece di fare un loop infinito che ti interferisce con l'event loop di Qt

    connect(socket,&QTcpSocket::diconnected,[&]()->void{socket->abort();
               socket->connectToHost(QHostAddress("192.168.0.12"), 5000);});
    

Log in to reply
 

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