Я было думал, что "поток" в контексте передачи данных через TCP - это в самом деле поток. С одной стороны байты кладёшь, с другой читаешь - и не важно, как именно их кладёт передатчик (в смысле, всей кучей сразу или же один за одним, медленно, с достоинством): передатчик получит их, когда прочитает буфер.
То есть, например, передатчик делает так:
send (socket, &command, 2, 0); // command - 16-битное целое, некий идентификатор
send (socket, &dlength, 2, 0); // dlength - кол-во байт данных, опционально следующих за этим заголовком
if (dlength > 0) send (socket, data, dlength, 0); // сами данные, их может и не быть
...и приёмник имеет, как я надеялся, полное право читать аналогичным орочьим способом:
tcpSocket->read((char*)&serv_cmd, 2);
tcpSocket->read((char*)&serv_dlen, 2);
if (serv_dlen > 0)
{
tcpSocket->read(buf, serv_dlen);
}
Так вот, это нихера не работает по непонятной мне причине.
Во-первых, эксперимент показал: таки надо дождаться
tcpSocket->waitForReadyRead(-1);
, иначе из сокета читаются просто нули. Чтение типа блокирующее, но оно успешно завершается, когда никаких данных ещё нет! Если же дождаться готовности, тогда чтение работает более корректно. И есть нюанс: всё это где-то ломается на этапе записи данных.
Если я на передающей стороне пишу в сокет сразу ВЕСЬ массив байтов (а не отдельно заголовок, отдельно данные), тогда чтение не сбивается. Но если я передаю порциями, тогда процесс спотыкается и может два раза может два раза прочитать одно и то же прочитать одно и то же. Или не прочитать что-то, что совершенно точно было выслано. И все это потому, что POSIX send() на самом деле, похоже, высылает данные пакетом (а не складывает их где-то в буфере).
Попробовал перед каждым вызовом метода read() воткнуть waitForReadyRead -- не помогло, программа стала просто вся целиком виснуть.
Прочитать "всё целиком", наверное, как-то можно, но только ведь объём присылаемых данных заранее неизвестен. Как быть?