Так-то оно всё так, но с Modbus/TCP есть некоторые особенности,
возникшие "по историческим причинам". 1. В своё время длина сообщения в modbus/RTU была ограничена до 256 байт. Для возможности конвертирования /TCP <==> /RTU оставили ограничение на размер PDU и теперь блок данных в /TCP не может быть больше 7(MBAP)+253(PDU) = 260 байт. Хотя само устройство сообщений модбаса позволяет упаковывать в них до 64К данных.
2. Судя по всему, оконечные устройства(контроллеры) в те годы были весьма хилыми. Им облегчили задачу разбора, установив что начало сообщения всегда совпадает с началом фрейма(сегмента) TCP.
В той-же LwIP в варианте NOSYS и по сей день пакетная структура TCP торчит наружу через все абстракции и её невозможно игнорировать.
В MODBUS Messaging Implementation Guide 1_0b.pdf на стр.10:
6) A TCP frame must transport only one MODBUS ADU. It is advised against sending multiple MODBUS requests or responses on the same TCP PDU
На "большом брате" можно в свойствах сокета отключить объединение коротких последовательных сегментов в один, более длинный (алгоритм Нэйгла):
setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, ...)
А можно и не отключать, в типичном случае после отправки запроса всё равно ждем ответа от слейва. Все и так будет работать, в худшем случае, если замешкаться, один запрос уйдет несколькими фреймами, а следующий запрос автоматом попадает в начало фрейма, что и требовалось.