Solved 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 nullaEdit: 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 diDATI* 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 adisconnected
ivece di fare un loop infinito che ti interferisce con l'event loop di Qtconnect(socket,&QTcpSocket::diconnected,[&]()->void{socket->abort(); socket->connectToHost(QHostAddress("192.168.0.12"), 5000);});