Возможно ли у получателя определить «границы пакетов» TCP отправителя?
Коллеги, кривоватый получился вопрос. Уточню. Итересует ответ от специалистов, хорошо понимающих TCP/IP.
Насколько я понимаю, MTU для Ethernet - около 1500 байт. Соответственно, если я делаю отправку в сокет меньшего количества байтов, то они могут задержаться в буфере до следущей (нескольких) отправок, если нет флага PSH. Всё так?
Получатель (для примера примере возьмём NodeJS) будет дергать колбек на получение данных в сокет для каждого моего "сообщения". Для каждой моей отдельной посылки, меньшей 1500 и снабженной PSH. А может получиться так, что пакет по дороге фрагментируется? И придёт двумя TCP-пакетами? И тогда я получу два вызова колбека?
Или, если я отправлю более 1500, тогда это точно уходит несколькими пакетами. Это будет несколько вызовов колбеков на принимающей стороне? Гарантированно столько, сколько пакетов или непредсказуемо? Или на это еще может наложиться цикличность опроса в event-машине NodeJS и вычиток и колбеков может быть иное количество?
Я пробую из одного процесса nodejs в другой кинуть в сокет 60К и получаю 4 вызова колбека на приёмнике. Это вроде бы меньше, чем по вызову на пакет, но и больше чем один вызов на всю посылку.
Соответственно, вопроса два:
- Предсказуемо ли количество колбеков?
- Можно ли понять, что вот эти несколько TCP-пакетов - это одна посылка клиента? Видел в анализаторе некие reassembled-пакеты, но пока не понял, про что это.
Вопрос задаю потому что хочу узнать - могу ли я на приёмнике получать как бы события "клиент отправил посылку". И не важно во сколько это уложилось TCP-пакетов.
Или нет? Или просто труба из которой байты валятся в правильном порядке, но без каких либо границ, или как минимум не соответствующих операциям записи в сокет у отправителя.
Дмитрий Энтелис: Погляжу socket.io. Но у меня вопрос скорее абстрактный, чем именно про NodeJS. Вопрос собственно к тому, что при передаче шифрованных данных надо понимать - кончился блок или нет. Или здавать размеры блока отдельно. Видимо надо изучить детали реализации SSL и не смешивать несколько уровней в один.
Если коротко - вы должны отправлять перед передачей данных длину передаваемого, затем принимать куски, суммировать их длины и собирать из них итог.
Вы никогда не должны завязываться на то, что TCP внутри себя режет поток байт на датаграммы. Для программиста TCP - труба о двух сокетах, один - на клиенте, второй - на сервере.
Ну я как-бы так и сделал:
>В результате ничего лучше не придумал как сначала отправлять размер файла, а потом просто считать кол-во принятых байт чтобы знать где конец.
Scorpi: Да, но в процессе вы сделали много очень опасных допущений, которые делать не следует. Полистайте учебник, там много полезного о передаче данных по сети.
Я пытался сделать принималку изображений по TCP на node.js и тоже столкнулся с этой проблемой.
В результате ничего лучше не придумал как сначала отправлять размер файла, а потом просто считать кол-во принятых байт чтобы знать где конец.
Сейчас погуглил, и пишут что можно узнать где конец передачи по \n
Т.е. если пришёл end-line - значит передача закончена.
Вот это странно. Я стандарт не досконально читал, но насколько мне известно - нет там никаких управляющих символов. CRLF - это уже из области прикладного протокола. Например, в HTTP отделяет заголовки от тела. В моём случае данные - бинарные. Вводить управляющий символ - не хочется. Поэтому и пытаюсь понять - на основе самих пакетов TCP можно ли понять - начало/конец передачи в рамках одного соединения...
Павел Китьян: кажется нашёл кое-что. С помощью connection.end() можно вызвать callback "end" на серверной стороне. Т.е. начинаем и принимаем данные по callback'у data, а когда данные заканчиваются нам приходит callback end. stackoverflow.com/a/24876432/689289