S
S
sddvxd2018-09-09 23:38:42
Qt
sddvxd, 2018-09-09 23:38:42

How to implement forwarding over TCP in blocks?

Hello. There is a client and a server, the client sends blocks of 6 bytes (the first 2 per size) and the server seems to be receiving 6 bytes each:
Client:

void Client::slotReadyRead(){
    QDataStream in(pSocket);
    in.setVersion(QDataStream::Qt_5_3);

    for(;;){

        if(!nNextBlockSize){
            if(pSocket->bytesAvailable() < sizeof(quint16)){
                return;
            }
            in >> nNextBlockSize;
        }



        if(pSocket->bytesAvailable() < nNextBlockSize){
            return;
        }
        QString str;

        in >> str;

        QString strMessage = str;
        pTextEdit->append(str);
        nNextBlockSize = 0;
    }
}

void Client::slotSendToServer(){
    QByteArray arrBlock;

    QDataStream bufferOut(&arrBlock, QIODevice::WriteOnly);
    bufferOut.setVersion(QDataStream::Qt_5_3);
    bufferOut << pLineEdit->text();

    int lenData = arrBlock.size();
    int nBlockSize = 4;
    for(int j = 0; lenData > j && lenData >= nBlockSize; j += nBlockSize){
        for(int i = 0; i < sizeof(quint16); i++)
            arrBlock.insert(0, 0x01);
        bufferOut.device()->seek(0);
        bufferOut << quint16(nBlockSize);
        pSocket->write(arrBlock, nBlockSize + sizeof (quint16));
        arrBlock.remove(0, nBlockSize + sizeof(quint16));
    }

    if(lenData % nBlockSize != 0 && lenData){
        for(int i = 0; i < sizeof(quint16); i++)
            arrBlock.insert(0, 0x01);
        bufferOut.device()->seek(0);
        bufferOut << quint16(lenData);
        pSocket->write(arrBlock, lenData + sizeof (quint16));
    }



    pLineEdit->setText("");
}

Server:
void Server::sendToClients(const QString& str){

    QByteArray arrBlock;

    int nBlockSize = 4;
    int lenData = arrBlock.size();

    for(int i = 0; connections.count() > i; i++){

        QByteArray buffer(arrBlock);
        QDataStream bufferOut(&buffer, QIODevice::WriteOnly);
        bufferOut.setVersion(QDataStream::Qt_5_3);
        bufferOut << str;

        for(int j = 0; lenData > j && lenData >= nBlockSize; j += nBlockSize){
            for(int i = 0; i < sizeof(quint16); i++)
                arrBlock.insert(0, 0x01);
            bufferOut.device()->seek(0);
            bufferOut << quint16(nBlockSize);
            connections[i]->write(buffer, nBlockSize  + sizeof (quint16));
            buffer.remove(0, nBlockSize + sizeof(quint16));
        }

        if(lenData % nBlockSize != 0 && lenData){
            for(int i = 0; i < sizeof(quint16); i++)
                arrBlock.insert(0, 0x01);
            bufferOut.device()->seek(0);
            bufferOut << quint16(lenData);
            connections[i]->write(buffer, lenData  + sizeof (quint16));
        }
    }

}

void Server::slotReadClient(){
    QTcpSocket* pSocket = (QTcpSocket*)sender();
    QDataStream in(pSocket);
    in.setVersion(QDataStream::Qt_5_3);
    //QByteArray debug = pSocket->readAll();

    for(;;){
        if(!nNextBlockSize){
            if(pSocket->bytesAvailable() < sizeof(quint16)){
                return;
            }
            in >> nNextBlockSize;
        }
        if(pSocket->bytesAvailable() < nNextBlockSize){
            return;
        }
        QString str;

        in >> str;

        QString strMessage = str;
        pTextEdit->append(strMessage);
        nNextBlockSize = 0;


        sendToClients(pSocket->peerAddress().toString() + " написал: " + str);
    }

}

However, QByteArray debug = pSocket->readAll();all bytes get into it at once, and there are always more of them than necessary. Please help me understand

Answer the question

In order to leave comments, you need to log in

1 answer(s)
L
laphroaig, 2018-09-10
@laphroaig

TCP is a streaming communication protocol, so on the receiving end you cannot make any assumptions about how the data was transmitted by the client. TCP guarantees only serial receipt of data, and how they arrive, all at once or byte by byte, is not important. By tweaking some socket options, you can achieve this behavior, but this is fundamentally not the right approach.
Just imagine that the data comes one byte at a time (theoretically this is possible), you only need to implement reading and blocking according to your message format. And one message can come and one byte from the next, and so on.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question