Что происходит, когда процесс пытается прочитать больше байтов, чем тот, который его отправил

#sockets

#сокеты

Вопрос:

Если два процесса обмениваются данными через сокеты, и процесс A отправляет процессу B 100 байт.
Процесс B пытается прочитать 150 байт. Более поздний процесс A отправляет 50 байт.
Каков результат чтения процесса B? Будет ли процесс B read ждать, пока не получит 150 байт?

Ответ №1:

Это зависит от многих факторов, особенно связанных с типом розетки, но также и от времени.

Однако, как правило, размер приемного буфера считается максимальным. Итак, если процесс выполняет a recv с размером буфера 150, но операционная система пока получила только 100 байт от однорангового сокета, обычно доступные 100 доставляются принимающему процессу (и возвращаемое значение системного вызова будет отражать это). Принимающее приложение несет ответственность за возврат и recv повторное выполнение, если оно ожидает дополнительных данных.

Другой связанный фактор (который обычно не имеет места при короткой передаче, например, 150 байт, но определенно будет, если вы отправляете мегабайт, скажем) заключается в том, что, по-видимому, «атомарный» отправитель send из 1000000 байт не будет доставлен в одном пакете получающему узлу, поэтому, если у получателя естьпри соответствующем recv буфере в 1000000 байт очень маловероятно, что все данные будут получены за один вызов. Опять же, ответственность за продолжение вызова лежит на получателе recv до тех пор, пока он не получит все отправленные данные.

И, как правило, отправитель и получатель несут ответственность за то, чтобы каким-то образом согласовать ожидаемый размер. Один из распространенных способов сделать это — включить заголовок фиксированной длины в начале каждой логической передачи, сообщающий получателю, сколько байтов следует ожидать.

Ответ №2:

Зависит от того, какой это сокет. Для сокета ПОТОКА чтение вернет либо объем данных, доступных в данный момент, либо запрошенный объем (в зависимости от того, что меньше), и будет блокировать (ждать) только в том случае, если нет доступных данных.

Итак, в этом примере, предполагая, что 100 байт (все) были переданы и получены в буфер приема, когда B считывает данные из сокета, а дополнительные 50 байт еще не были переданы, чтение вернет эти 100 байт и не будет ждать.

Обратите также внимание на зависимость всех передаваемых и принимаемых данных — когда процесс A записывает данные в сокет, они не обязательно будут отправлены немедленно или все сразу. В зависимости от базового транспорта существует размер MTU, и любая запись, превышающая его, будет разбита. Меньшие записи также могут быть отложены и объединены с более поздними записями для создания MTU. Таким образом, в вашем случае отправка 100 байт может быть слишком большой (и разбитой) или может быть слишком маленькой и передаваться не сразу.