Qt QIODevice :: write / QTcpSocket :: write и записанные байты - PullRequest
4 голосов
/ 22 сентября 2011

Мы весьма озадачены поведением QIODevice::write в целом и реализацией QTcpSocket в частности.Уже есть подобный вопрос , но ответ на самом деле не является удовлетворительным.Основная путаница связана с упомянутым сигналом bytesWritten и, соответственно, waitForBytesWritten.Эти два, кажется, указывают байты, которые были записаны из буфера, используемого QIODevice, на фактическое базовое устройство (такой буфер должен быть, в противном случае метод не будет иметь большого смысла).Тогда возникает вопрос, соответствует ли число, возвращаемое QIODevice::write этому числу, или если в этом случае оно указывает количество байтов, которые были сохранены во внутреннем буфере ,не байты, записанные на базовое устройство .Если возвращаемое число будет указывать байты, записанные во внутренний буфер, нам нужно будет использовать шаблон, подобный следующему, чтобы гарантировать, что все наши данные записаны:

void writeAll(QIODevice& device, const QByteArray& data) {
   int written = 0;
   do {
     written = device.write(data.constData() + written, data.size() - written);
   } while(written < data.size());
}

Однако при этом будут вставлены повторяющиеся данные, есливозвращаемое значение QIODevice::write соответствует значению сигнала bytesWritten.Документация очень запутанная по этому поводу, так как в обоих методах используется слово device , даже если это кажется логичным и общее понимание, что на самом деле указывается запись в буфер, а не в device.

Итак, подведем итог: вопрос в том, вернулось ли число пока QIODevice::write количество байтов, записанных на базовое устройство, и, следовательно, его сохранение для вызова QIODevice::write без проверки возвращенного количества байтов, так как все хранится во внутреннем буфере.Или это указывает, сколько байтов он может хранить внутри, и шаблон, подобный приведенному выше, writeAll должен использоваться для безопасной записи всех данных на устройство?

(ОБНОВЛЕНИЕ: Глядя на источник, * 1031Реализация на самом деле никогда не вернет меньше байтов, чем один хотел написать, поэтому приведенное выше writeAll не требуется. Однако, это специфично для сокета и этой версии Qt, документация по-прежнему сбивает с толку ...)

Ответы [ 2 ]

5 голосов
/ 22 сентября 2011

QTcpSocket является буферизованным QAbstractSocket. Внутренний буфер расположен внутри QAbstractSocket, и данные копируются в этот буфер. Возвращаемое значение записи - это размер данных, переданных в write().

waitForBytesWritten ожидает, пока данные во внутреннем буфере QAbstractSocket не будут записаны в собственный сокет.

1 голос
/ 22 сентября 2011

Этот предыдущий вопрос отвечает на ваш вопрос, как и документация QIODevice::write(const char * data, qint64 maxSize):

Записывает максимум maxSize байтов данных из данных на устройство. Возвращает количество фактически записанных байтов или -1, если произошла ошибка.

Это может (и будет в реальной жизни) возвращать меньше, чем вы просили, и вы должны снова позвонить write с остатком.

Что касается waitForBytesWritten:

Для буферизованных устройств эта функция ожидает, пока на устройство не будет записана полезная нагрузка буферизованных записанных данных ...

Это относится только к буферизованным устройствам. Не все устройства буферизируются. Если они есть, а вы написали меньше, чем может вместить буфер, write может успешно вернуться до того, как устройство завершит отправку всех данных.

Устройства не обязательно буферизируются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...