Коротко — да. MSS/MTU задаёт только верхнюю границу полезной нагрузки TCP‑сегмента, а не жёсткий размер каждого отправляемого сегмента. В вашем примере (rwnd=4000, MSS=1000, в буфере 6000) обычно можно отправить четыре полных сегмента по 1000 байт, но в ряде ситуаций TCP может отправить и меньшие сегменты. Основные случаи:
- Оставшиеся данные меньше MSS. Если в буфере осталось <1000 байт, финальный сегмент будет меньшим.
Пример: осталось 500 байт → сегмент 500 байт.
- Ограничение по cwnd (congestion window). TCP шлёт не больше min(cwnd, rwnd, данные). Если cwnd не кратно MSS или вообще меньше 4·MSS, последний допустимый сегмент может быть меньше MSS.
Пример: cwnd = 3500 → можно отправить 3×1000 и 1×500.
- Режим восстановления после потерь / частичные подтверждения. При fast recovery/partial ACK TCP может отправлять сегменты, размер которых соответствует освободившемуся «праву» на передачу — они могут быть неравны MSS.
- Малые записи приложения / политика сокета. Если приложение делает write() на <MSS байт и TCP решит немедленно передать (например, нет незакрытых данных, или отключён Nagle/TCP_NODELAY), отправится маленький сегмент.
- Nagle/Delayed ACK взаимодействие. Nagle старается избегать мелких сегментов, но при определённых условиях (нет несёмых неподтверждённых данных, или после получения ACK) маленький сегмент всё равно будет отправлен.
- Window‑probe (zero‑window probe). При закрытом окне отправляются маленькие (часто 1 байт) пакеты для проверки окна.
- FIN/закрытие соединения. FIN занимает номер последовательности и может быть отправлен вместе с небольшим количеством данных или отдельно в маленьком сегменте.
- Path MTU / изменение условий на пути. Если обнаружится меньшая MTU, стек может уменьшить размер данных в сегментах (MSS обычно согласуется в начале, но практическая максимальная полезная нагрузка может быть уменьшена).
Примечание про TSO/GSO: сетевые драйверы/ничи могут агрегировать большие буферы и разбивать их на MSS‑слоты в NIC; это не отменяет того, что «на провода» пойдут сегменты не больше MSS, а последний фрагмент может быть меньше.
Итого: MSS — максимум, а не обязательный размер. Мелкие сегменты встречаются в ряде обычных ситуаций, особенно при ограничениях cwnd/rwnd, при остаточных данных, при работе механизмов управления (Nagle, recovery, window probe) или из‑за поведения приложения.