В соединении TCP отправитель использует write()
(возможно, в цикле) для отправки данных.На стороне получателя read()
копирует полученные данные из буфера сокета в ваш буфер на уровне приложения.Если один метод write () отправит, скажем, 900 байтов, TCP может разбить его на несколько кусков разных размеров ... например, 300, 400 и 200 байтов, поэтому на принимающей стороне необходимо три раза вызвать read()
, чтобыполучить все данные.
Теперь, если вы поместите recv()
в цикл и каждый раз, когда он заполняет весь буфер или его часть, как вы узнаете, когда прекратить прием?Когда отправитель отправляет все данные и изящно закрывает соединение, ваш recv()
вернет 0
.Больше нечего получить, вы можете закрыть розетку.
Я упоминал о заполнении буфера в цикле.Если вы не обрабатываете данные из принимающего буфера в цикле recv()
, вам нужно сохранить его где-нибудь, иначе каждая итерация может перезаписать его.(Вы можете продвигать указатель буфера в каждой итерации, но это будет работать, только если вы заранее знаете длину пакета.) Вы можете скопировать каждый полученный кусок в очередь или какую-либо другую структуру данных.Обработка данных обычно идет параллельно с получением данных - и в другом потоке обработки.
Но вернемся к циклу recv()
.Помимо ожидания 0
, есть еще одна хитрость того, как получатель может знать, когда прекратить прием: отправитель и получатель могут договориться (знать), что, например, первые два отправленных байта будут содержать длину сообщения .Поэтому в начале получатель будет ждать только два байта.Получив их, он распакует информацию о размере сообщения, скажем, 900 байтов.Теперь получатель может настроить свой размер буфера до 900 и принимать в цикле, пока не будут получены все 900 байтов.Каждый recv()
будет возвращать количество полученных байтов, и получатель может продвигать указатель буфера на это количество байтов, поэтому следующий recv()
записывает в свободную часть буфера.
Кстати, эти общие знания (контракт) между клиентом и сервером (или получателем и отправителем) являются вашим протоколом связи на уровне приложения.Он поставляется поверх протокола TCP.