Этот вопрос закрыт для ответов, так как повторяет вопрос Почему приходит больше байт, чем указано?
@sddvxd

Как реализовать пересылку по TCP блоками?

Здравствуйте. Есть клиент и сервер, клиент отправляет блоки по 6 байтов (первые 2 на размер) и сервер, вроде бы как принимающий по 6 байтов:

Клиент:
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("");
}


Сервер:

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);
    }

}


Однако в QByteArray debug = pSocket->readAll(); попадают сразу все байты, причем всегда их приходит больше, чем нужно. Помогите пожалуйста разобраться
  • Вопрос задан
  • 164 просмотра
Ответы на вопрос 1
@laphroaig
TCP это потоковый протокол передачи данных, поэтому на принимающей стороне вы не можете делать никаких предположений о том, каким образом данные были переданы клиентом. TCP гарантирует только последовательное получение данных, а уж как они приходят, все разом или по байту, не важно. Подкрутив некоторые опции сокетов, можно добиться такого поведения, но это принципиально не верный подход.

Просто представьте себе, что данные приходят по одному байту за раз (теоретически такое возможно), вам только нужно реализовать чтение и разделение на блоки в соответствии вашим форматом сообщений. А может прийти одно сообщение и один байт от следующего и т.д.
Ответ написан
Ваш ответ на вопрос

Вопрос закрыт для ответов и комментариев

Потому что уже есть похожий вопрос.
Похожие вопросы