В начале кадра UART, открываешь соединение TCP. И все данные кадра,
передаёшь в этом, открытом соединении, по факту прихода, хоть по 5
байт - не важно, TCP всё стерпит. На стороне приёма, забиваешь буфер, скажем, в 128 байт (определяется опытным путём - чтобы исключить перерывы в передаче восстановленного кадра из-за разницы скоростей и из-за задержек IP) и, как буфер достиг целевого размера, передаёшь восстановленный фрейм без перерыва до получения команды на закрытие соединения.
Как только на стороне UART-источника обнаружен конец кадра (по разделителю или по межкадровой паузе) - завершаешь TCP соединение. Приёмная сторона, по команде close, формирует межкадровый промежуток - паузу. И ждёт следующего соединения, чтобы начать приём следующего кадра.
Почему рекомендую такой подход - по соединению на кадр? Потому, что в рамках одного соединиения TCP, невозможно надёжно определить обрыв связи. В моей практике, бывало, обнаружение пропажи связи происходило лишь через 20 минут после фактического прекращения трафика. TCP не умеет быстро обнаруживать отказ. Поэтому на каждый кадр - своё соединение. Так обе стороны, пытаясь выполнить передачу кадра - новое согласование соединения - обнаружат отказ сразу.