С «пакетами» фиксированного размера мы обычно хотели бы, чтобы каждый пакет, кроме последнего, был полностью заполнен действительными данными. Только последний будет «частичным», и если получатель знает, сколько байтов ожидать (потому что, по предложению Давиты, отправитель заранее указал размер файла), тогда это не проблема. Получатель может просто игнорировать остаток последнего пакета.
Но ваше дальнейшее описание звучит так, будто может быть несколько частично полных пакетов, связанных с передачей одного файла. Существует аналогичное простое решение: префикс каждого пакета с количеством действительных байтов.
Вы позже упоминаете TCustomWinSocket.ReceiveText
, и вам интересно, как он знает, сколько текста нужно прочитать, а затем вы цитируете ответ, то есть он вызывает ReceiveBuf(Pointer(nul)^, -1))
, чтобы установить длину буфера результата перед его заполнением. Возможно, вы просто не поняли, что делает этот код. Это легче понять, если вы посмотрите на этот тот же самый код в другом контексте, метод ReceiveLength
. Он делает тот же самый вызов ReceiveBuf
, указывая, что когда вы передаете -1 в ReceiveBuf
, он возвращает количество полученных байтов.
Чтобы это работало в ваших целях, вы не можете отправлять пакеты фиксированного размера. Если вы всегда отправляете пакеты размером 32 КБ и просто заполняете конец нулями, то ReceiveLength
всегда будет возвращать 32768, и вам придется объединить решения Дэвиты и моего с отправкой файлов и длины пакетов вместе с полезной нагрузкой. Но если вы убедитесь, что каждый байт в вашем пакете всегда действителен, получатель может узнать, сколько сэкономить, исходя из размера пакета.
Так или иначе, вам необходимо убедиться, что отправитель предоставляет получателю информацию, необходимую ему для выполнения своей работы. Если отправитель отправляет мусор, не давая получателю способа отличить мусор от действительных данных, вы застряли.