write() is faster than read() in TCP Connection using Qt C++

123 views Asked by At

I am experiencing issues where block of data written into a socket within a QTimer in a server application ,which can't be read by the client completely because the client's read process is slow, so when I stop the qtimer by clicking stop button ,the unread data failed to be read by the client.

My Intensions :

  1. A Start Server button is clicked to start the server and then a connect button is clicked in by the client to connect to the host.

  2. The input should be entered in the server window and the start button button is clicked in the client to increase the value by 1.(Frequency,Attenuation,Snr,Temperature)

  3. After Increment, these values will be write in the socket inside QTimer and send to the client.

  4. I used QByteArray and QDatastream for communication.The datas were send and received in blocks.

  5. I used QTimer to populate my QWidgetTable.

  6. After clicking Stop button by the client the increment process will be stopped.Finally by clicking didconnect button the client will be disconnected.

  7. The Main point is the output values should be same in both server and client.

My intensions above mentioned were achieved successfully,expect point no.7 .The read process of the client is really slow, so when click the stop button it doesn't read the already written data by the server to the socket.I have more values in server window and less values in client window.

Any help will be appreciated ! Thank you in advance :)

Left one is Client window and the right one is Server window: Left side-Client window , Right side-Server window

A part of my server code:

Server.cpp

void Server::readyRead()
{
nextBlockSize = 0;
QTcpSocket *client = (QTcpSocket*)sender();
qDebug() << client;
QDataStream in(client);
in.setVersion(QDataStream::Qt_6_5);
if (nextBlockSize == 0) {
    if (client->bytesAvailable() < sizeof(quint16))
        return;
    in >> nextBlockSize;
}
if (client->bytesAvailable() < nextBlockSize)
    return;

QString header;
QString cid;
QString footer;
in >> header;
in >> cid;
in >> footer;
if (cid == "0x1B10") {
    m_pWindow->addMessage("Client Connected");
}
if(cid =="0x1A10")
{
    m_pWindow->addMessage("Process Started");
    process();
}
 if(cid =="0x1A20")
{
    m_pWindow->addMessage("Process Stopped!");
    m_timer->stop();
}
 QDataStream out(client);
 out << quint16(0xFFFF);
 close();
 if(cid=="0x1B20")
 {
    m_pWindow->addMessage("Client Disconnected");
    disconnected();
 }

}

void Server::process()
{
m_timer = new QTimer(this);
connect (m_timer, SIGNAL(timeout()), this, SLOT(passvalue())) ;
m_timer->start(1000);
}

void Server::passvalue()
{
m_pWindow->getinput();
}

void Server::increment(int freq, int att, int snr, int temp)
{
if(freq>=3000)
    freq=20;
if(att>=100)
    att=0;
if(snr>=10)
    snr=0;
if(temp>=30)
    temp=0;
freq++;
att++;
snr++;
temp++;
bool success=m_pWindow->updateTable(freq,att,snr,temp);

if(success)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::ReadWrite);
    out.setVersion(QDataStream::Qt_6_5);
    quint16 header=rand();
    quint16 payload1=freq;
    quint16 payload2=att;
    quint16 payload3=snr;
    quint16 payload4=temp;
    quint16 size=sizeof(payload1)+sizeof(payload2)+sizeof(payload3)+sizeof(payload4);
    quint16 footer=rand();
    out << quint16(0) << header << size << payload1 << payload2 << payload3 << payload4  << footer  ;
    uint16_t cs=checksum(block,size);
    out << cs;
    out.device()->seek(0);
    out << quint32(block.size() - sizeof(quint16));
    foreach (QTcpSocket *socket, clients)
    {
        qDebug() << socket;
        socket->write(block);
        socket->waitForBytesWritten();
    }
}

}

A part of my client code :

dialog.cpp

void Dialog::readyRead()
{
nextBlockSize = 0;
QDataStream in(m_pClientscket);
m_pClientscket->waitForBytesWritten();
m_pClientscket->waitForReadyRead();
in.setVersion(QDataStream::Qt_6_5);
if (nextBlockSize == 0) {
    if (m_pClientscket->bytesAvailable() < sizeof(quint16))
        return;
    in >> nextBlockSize;
}
if (m_pClientscket->bytesAvailable() < nextBlockSize)
    return;
quint16 header;
quint16 payload1;
quint16 payload2;
quint16 payload3;
quint16 payload4;
quint16 size;
quint16 footer;
uint16_t cs;
updateTable(payload1,payload2,payload3,payload4);

}

void Dialog::updateTable(int freq,int att,int snr,int temp)
{
QTableWidgetItem *item;
ui->tableWidget->insertRow( ui->tableWidget->rowCount() );
for(int j=0;j<4;j++)
{
    item= new QTableWidgetItem;
    if(j==0)
        item->setText(QString::number(freq));
    if(j==1)
        item->setText(QString::number(att));
    if(j==2)
        item->setText(QString::number(snr));
    if(j==3)
        item->setText(QString::number(temp));
    ui->tableWidget->setItem(i,j,item);

}
ui->textEditFrequency->setText(QString::number(freq));
ui->textEditAttenuation->setText(QString::number(att));
ui->textEditSnr->setText(QString::number(snr));
ui->textEditTemp->setText(QString::number(temp));
i++;
}


void Dialog::on_pushButtonStop_clicked()
{
QByteArray block;
QDataStream out(&block, QIODevice::ReadWrite);
out.setVersion(QDataStream::Qt_6_5);
QString header="0x228";
QString cid="0x1A20";
QString footer="0x497";
out << quint16(0) << header << cid << footer  ;
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));
m_pClientscket->write(block);
}
1

There are 1 answers

0
Belle On BEST ANSWER

I used QByteArray to read the data which is sent from the server to client using readAll() function.This solved my problem.

dialog.cpp

void Dialog::readyRead()
{
    QByteArray data = m_pClientscket->readAll();  // Read all available data
    QDataStream in(data);
    in.setVersion(QDataStream::Qt_6_5);
    quint16 header;
    quint16 blocksize;
    quint16 payload1;
    quint16 payload2;
    quint32 payload3;
    quint32 payload4;
    quint16 size;
    quint16 footer;
    uint16_t cs;
    in >> header >> blocksize >> size >> payload1 >> payload2 >> payload3 >> payload4 >> footer >> cs   ;
    qDebug()  << header << size << payload1 << payload2 << payload3 << payload4 <<  footer << cs;

    updateTable(payload1,payload2,payload3,payload4);
}