Как уже упоминалось, TCP - это потоковый протокол. Это означает, что с точки зрения API нет понятия «пакет». Как пользователь, все, что вы можете ожидать, это поток данных.
Внутренне TCP будет разбивать поток на сегменты, которые могут быть помещены в IP-пакеты. Эти пакеты будут отправлены вместе с управляющими данными через IP на удаленный конец. Удаленный конец получит эти IP-пакеты. Он может отбрасывать определенные IP-пакеты (в случае дубликатов), переупорядочивать пакеты или удерживать данные до тех пор, пока не будут получены более ранние пакеты. Все это является внутренним для TCP, то есть понятие «пакет TCP» не имеет смысла.
Возможно, вы сможете использовать необработанные сокеты для получения необработанных IP-пакетов, но это будет означать, что вам придется переопределять большую часть стека TCP (например, отправлять ACK и настраивать размер окна), чтобы удаленный конец работал правильно. Вы не хотите этого делать.
UDP, с другой стороны, является протоколом дейтаграмм. Это означает, что пользователь осведомлен о том, как данные отправляются по сети. Если для вас важна концепция пакетов или дейтаграмм, вам нужно будет создать собственный протокол поверх UDP.