Russian Qt Forum

Qt => Работа с сетью => Тема начата: Yury от Январь 26, 2018, 13:34



Название: Работа с QTcpSocket
Отправлено: Yury от Январь 26, 2018, 13:34
Всем привет.
Пишу клиент-серверное приложение по передаче файлов по сети и есть вопрос.
Как только на сервере я записываю данные в сокет методом write(),то на каждый его вызов на клиенте срабатывает сигнал readyRead(), правильно?И каждый сигнал обрабатывается слотом.
А если я на сервере вызову в цикле 10 раз метод write() с новым QByteArray каждый раз в качестве аргумента?На клиенте мне приходит только самый первый пакет,остальные 9 почему-то не доходят,хотя с сервера вроде ушли.

В чем может быть дело?И как мне лучше переслать 10 файлов с сервера на клиент?


Название: Re: Работа с QTcpSocket
Отправлено: Yury от Январь 26, 2018, 13:37
Вот мой код:

void MainWindow::sendToServer(const QString &msg)
{
    Package package;
    package.smallNum = 4;
    package.bigNum = 1567;
    package.str = msg;
    package.array = "jkgferwgfrewjfwewef";

    QByteArray arrBlock;
    QDataStream out(&arrBlock, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_8);

    out << package.smallNum;
    out << package.bigNum;
    out << package.str;
    out << package.array;

    int lBytes = 0;

    lBytes = tcpSocket->write(arrBlock);

    qDebug() << lBytes << "were sent";
}

void MainWindow::slotConnected()
{
    ui->textEdit->append("Recieved the connected() signal from server");
}

void MainWindow::slotSendButton()
{
    int packageNum = 0;
    for(int i = 0; i < 10; ++i) {
    packageNum++;
    sendToServer("Hello, server. How are you? " + QString::number(packageNum));
    }
}

То есть по нажатию кнопки 10 раз вызовется wriye(), а на другом конце сигнал readyRead() срабатывает только раз.Иногда 2)


Название: Re: Работа с QTcpSocket
Отправлено: vicprog от Январь 26, 2018, 14:18
Как мне кажется, ты забыл сделать после

Код:
tcpSocket->write(arrBlock);
tcpSocket->flush();

Размер пакета для tcp в среднем около 1500 байт. Посчитай сам, сколько туда твоих сообщений поместится.


Название: Re: Работа с QTcpSocket
Отправлено: Yury от Январь 26, 2018, 14:26
С flush() уже доходит 2 пакета,но все равно не все)Остальные 8 теряются.Размер одного отсылаемого пакета тут около 90 байт,не больше 100.


Название: Re: Работа с QTcpSocket
Отправлено: vicprog от Январь 26, 2018, 14:40
Посмотрите, что flush возвращает.
Еще можно поставить waitForBytesWritten() и тоже посмотреть что возвращает.
А еще посмотрите на размер приходящих пакетов. Может они спресовались в один пакет?


Название: Re: Работа с QTcpSocket
Отправлено: ssoft от Январь 26, 2018, 14:43
Несколько пакетов может объединяться в один readyRead, все ли данные вычитываются?


Название: Re: Работа с QTcpSocket
Отправлено: kuzulis от Январь 26, 2018, 15:16
Цитировать
Как только на сервере я записываю данные в сокет методом write(),то на каждый его вызов на клиенте срабатывает сигнал readyRead(), правильно?И каждый сигнал обрабатывается слотом.

Нет. QTcpSocket полностью асинхронный. Вызов QTcpSocket::write() пишет данные во внутренний буффер кдасса QTcpSocket, а уже там, далее эти данные могут быть посланы позже. Все зависит от внутреннего сосояния QTcpSocket и платформы на которой он реализован.

В общем случае вот это:

Код:
void Foo::bar()
{
    socket.write('A');
    socket.write('B');
    socket.write('C');
}

Не гарантирует что оно будет отослано по-отдельности и прямо сейчас.
Оно все зависит от фазы луны, настроект сокета и прочего всего. :)

Скорее всего QTcpSocket возмет сразу ABC и запишет в FIFO драйвера (а может и не сразу),
а как там уже драйвер отправит их, одному Лешему известно. 


Название: Re: Работа с QTcpSocket
Отправлено: Yury от Январь 26, 2018, 15:34
Да,вы правы!Приходят не по отдельности пакеты,а вместе скомканные.А как их тогда лучше обработать,чтобы разделить на клиенте?Сначала в буфер записать и потом вычленять из него?


Название: Re: Работа с QTcpSocket
Отправлено: kuzulis от Январь 26, 2018, 16:10
Цитировать
Сначала в буфер записать

QTcpSocket уже имеет буфер, т.о. нет необходимости в каком-то дополнительном буфере (но тут кому как удобнее).

Цитировать
и потом вычленять из него?

Да, для этого нужно иметь какой-то протокол обмена (типо придумать заголовки к данными, типа 0x55AA).
Для парсинга данных достаточно юзать peek(), read(), bytesAvailable().


Название: Re: Работа с QTcpSocket
Отправлено: vicprog от Январь 26, 2018, 16:31
Все зависит от решаемой задачи. Если клиент может подождать и обработать потом пачку сообщений - то да, делать как в предыдущем сообщении.
Если нельзя накапливать и нужна реакция на каждое сообщение - то смотреть в сторону QUdpSocket (но там возможна потеря сообщений при передачи).