Идёт активный опрос (вопрос-ответ) удалённой системы. Периодически не приходят целые цепочки (Прогресс роста ~ 1, 5, 50, 100, ...) ответов, хотя снифер видит соответствующие пакеты. Чем дольше программа работает, тем больше эти "провалы". За семь минут 200 пакетов.
Я чего то не пойму, Вы TCP используете? Или присоединенный UDP сокет? В первом случае ни о каких пакетах речь не может идти — транспортный драйвер собирает поток как ему заблагорассудится — может по байту отдавать, а может и по 10 кб — величина в общем случае не связана с размером пакета, переданного через сеть ( хотя естественно корреляция наблюдается обычно ). Если это UDP сокет — то при активном обмене может просто переполняться буфер драйвера, он не будет для вас там тыщщи пакетов хранить.
Вообще то ТСР (в имени функции присутствует).
Режим вопрос-ответ. Пакеты просто не могут переполнять буфер, поскольку приходят по одному.
Снифер их все видит.
И не понятно откуда берётся закономерность:
256-й
513, 515
771, 773, 775
1030, 1032, 1034, 1036
и т.д.
Если Вы работаете с TCP, то не стоит искать соответствия между получаемыми данными через ф. recv и принятыми пакетами. Т.е вы видите сниффером, что пришло 10 пакетов по протоколу TCP. Если Вы при этом в цикле вызываете recv — она может сработать от 0 до 10 раз ( а может и больше — зависит от размера буфера ). Если у Вас теряются данные — ищите ошибку в коде.
Ux>И не понятно откуда берётся закономерность: Ux>256-й Ux>513, 515 Ux>771, 773, 775 Ux>1030, 1032, 1034, 1036 Ux>и т.д.
А закономерностей искать не надо — этак можно до дурки дойти.
Здравствуйте, TarasCo, Вы писали:
TC>Если Вы работаете с TCP, то не стоит искать соответствия между получаемыми данными через ф. recv и принятыми пакетами.
Прийти должен только один пакет. И он приходит, но из сокета вычитать я его не могу. И не получаю каждый 256-й с ростом непринятых на один с чередованием через один.
TC>А закономерностей искать не надо — этак можно до дурки дойти.
Если бы она не повторялась на других компах. И в других компиляторах. В Висуал 6.0 та же фигня.
Здравствуйте, Ux, Вы писали:
Ux>Прийти должен только один пакет. И он приходит, но из сокета вычитать я его не могу.
Всё ты можешь, только зачем-то наворотил селектов с таймаутами (кстати, и даже после "неудачного" селекта ты всё равно можешь спокойно прочитать данные).
Ux>И не получаю каждый 256-й с ростом непринятых на один с чередованием через один.
Тебе уже объяснили два раза, почему это происходит.
Ux>Если бы она не повторялась на других компах. И в других компиляторах. В Висуал 6.0 та же фигня.
Причем тут компиляторы? Скажу тебе страшную тайну — точно такую же картину ты бы увидел и на Delphi и на C# и на Java
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Всё ты можешь, только зачем-то наворотил селектов с таймаутами (кстати, и даже после "неудачного" селекта ты всё равно можешь спокойно прочитать данные).
Иначе просто клинит программу на этом самом 256-м чтении. Прочитать данные соответственно не могу.
MC>Тебе уже объяснили два раза, почему это происходит.
Не объяснили.
Я всегда получаю целые пакеты.
75 байт данных, хотя буфер для ресива несколько больше.
Следующее обращение получает удачный ответ.
А через одно опять ошибка.
При этом более одного пакета данных за раз я не получаю.
Клиентская часть проверялась на двух компьютерах. Драйвера сетевых карт соответственно разные.
Возжность присутствия ошибки я признаю, но её найти не могу.
MC>Причем тут компиляторы? Скажу тебе страшную тайну — точно такую же картину ты бы увидел и на Delphi и на C# и на Java
Я не был бы столь категоричен.
П.С. Я просто хотел "услышать" мнение человека, который с таким сталкивался.
Здравствуйте, Ux, Вы писали:
MC>>Ладно, начнем сначала. Зачем тебе там вообще потребовался select с таймаутом? Ux>Для проверки наличия данных для чтения в сокете.
Зачем это тебе нужно? recv все равно вернет данные.
Ux>А что что-то не так?
Да все так, только ты почему-то удивляешься получению результата, ради которого и наворачивал весь этот код с select и таймаутом. Если бы твоя функция была из одной строчки (вызова recv), то у тебя бы не возникло вопросов.
MC>Зачем это тебе нужно? recv все равно вернет данные.
Не вернёт, если не было дисконекта, сокет блокируемый и пакет не пришёл. И будет тупо ждать данных.
Сделал одним ресивом с включеной опцией таймаута. Та же прогрессия пропадания пакетов.
Здравствуйте, Ux, Вы писали:
MC>>Зачем это тебе нужно? recv все равно вернет данные. Ux>Не вернёт, если не было дисконекта, сокет блокируемый и пакет не пришёл. И будет тупо ждать данных.
Пусть ждет. Нет данных — ждет, появятся — вернет. Пропадет передатчик — recv отвалится по таймауту сам, расценивай это как disconnect.
MC>Пусть ждет. Нет данных — ждет, появятся — вернет. Пропадет передатчик — recv отвалится по таймауту сам, расценивай это как disconnect.
1. А я думал, что дисконнект проверяется по возврату нуля от этой функции.
2. Мне что писать отдельный поток для приёма данных из сокета? А потом их синхронизировать?
3. Почему ни кого не удивляет наличие подобной прогрессии по пропаданию пакетов? На 256-м пакете прогу обязательно заклинит, а это 21-я секунда работы системы. Не помогает даже дисконнект и открытие новой сессии.
Здравствуйте, Ux, Вы писали:
MC>>Пусть ждет. Нет данных — ждет, появятся — вернет. Пропадет передатчик — recv отвалится по таймауту сам, расценивай это как disconnect.
Ux>1. А я думал, что дисконнект проверяется по возврату нуля от этой функции.
0 — другая сторона говорит что больше данных не будет. По соединению все еще можно передавать данные с твоей стороны.
-1 — ошибка, под виндой смело можешь считать что соединение сдохло.
Ux>2. Мне что писать отдельный поток для приёма данных из сокета? А потом их синхронизировать?
Нафига?
Ux>3. Почему ни кого не удивляет наличие подобной прогрессии по пропаданию пакетов?
Я уже устал повторять что никакого пропадания не происходит, дело в твоем коде с select и таймаутом.
А никого это не удивляет, поскольку так работает TCP. Для повышения скорости передачи данных TCP пытается обьединить как можно больше порций данных в один сегмент. Описание можешь почитать здесь. Отключается на стороне передатчика установкой опции TCP_NODELAY.
MC>0 — другая сторона говорит что больше данных не будет. По соединению все еще можно передавать данные с твоей стороны. MC>-1 — ошибка, под виндой смело можешь считать что соединение сдохло.
If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
MC>А никого это не удивляет, поскольку так работает TCP. Для повышения скорости передачи данных TCP пытается обьединить как можно больше порций данных в один сегмент.
Ну не объединяет он. В дампе снифера нормальные Езернет фреймы с одиночными пакетами. Всё в порядке вопрос-ответ.
Здравствуйте, Ux, Вы писали:
MC>>0 — другая сторона говорит что больше данных не будет. По соединению все еще можно передавать данные с твоей стороны. MC>>-1 — ошибка, под виндой смело можешь считать что соединение сдохло.
Ux>If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
И где отличия от того что я написал?
Слушай, я уже 10 лет этим кормлюсь. Неужели ты думаешь что данный текст мне неизвестен? Да я его наизусть знаю, как букварь.
MC>>А никого это не удивляет, поскольку так работает TCP. Для повышения скорости передачи данных TCP пытается обьединить как можно больше порций данных в один сегмент.
Ux>Ну не объединяет он. В дампе снифера нормальные Езернет фреймы с одиночными пакетами. Всё в порядке вопрос-ответ.
Вы, надеюсь, хотябы поняли, что в ТСР нет понятия "пакет" ?
А то блин... Маразм-то крепчает, от нас сейчас госструктура одна требует отправки сообщений некоего протокола "целым кол-вом штук в одном ТСР-пакете и чтоб пакет с начала сообщения начинался". Доводы и убеждения на них не действуют. "Хотим и всё". Приходится через задницу всё делать...
Re[16]: Пакеты иногда не приходят на сокет
От:
Аноним
Дата:
05.12.07 10:01
Оценка:
MC>Опять "пакеты" в TCP... MC>Я устал. RTFM.
imho, вопрос именования TCP сегментов пакетами не является таким уж принципиальным. Действительно, ранние RFC не использовали понятия packet применительно к TCP.
Transmission Control Protocol (TCP) accepts data from a data stream, 'segments' it into chunks, and adds a TCP header creating a TCP segment. The TCP segment is then encapsulated, into an IP datagram. A TCP segment is "the packet of information that TCP uses to exchange data with its peers." [1]
Note that the term TCP packet is now used interchangably with the term TCP segment. [2][3] Although in the original RFC segment usually referred to the TCP unit of data, datagram[4] to the IP unit and packet to the data communications network unit:
Processes transmit data by calling on the TCP and passing buffers of data as arguments. The TCP packages the data from these buffers into segments and calls on the internet module [e.g. IP] to transmit each segment to the destination TCP.[5]
Так что если назвать TCP сегмент пакетом искажения смысла не произойдет. Конечно же все дело в том как именно формируются эти самые сегменты (или пакеты).
Здравствуйте, AlexCrush, Вы писали:
AC>Вы, надеюсь, хотябы поняли, что в ТСР нет понятия "пакет" ? AC>А то блин... Маразм-то крепчает, от нас сейчас госструктура одна требует отправки сообщений некоего протокола "целым кол-вом штук в одном ТСР-пакете и чтоб пакет с начала сообщения начинался". Доводы и убеждения на них не действуют. "Хотим и всё". Приходится через задницу всё делать...
А как они намерены это проверять?
Здравствуйте, Аноним, Вы писали:
А>Так что если назвать TCP сегмент пакетом искажения смысла не произойдет.
В том-то и дело что происходит искажение смысла. Под "пакетом" люди чаще всего понимают то что получается за один вызов recv/recvfrom (лично я ни разу не видел на этом форуме другого толкования от людей, пишущих про пакеты в TCP). А сегменты TCP до такого уровня просто не доживают! Теоретически нет никакой связи между тем, сколько данных ты получаешь за один вызов recv и тем, каков размер сегмента TCP в данный момент. И даже с тем, какими порциями отправлял send на другой стороне. Поэтому все предположения и выводы насчет пакетов в TCP неверны в корне.
Здравствуйте, Garrett, Вы писали:
AC>>А то блин... Маразм-то крепчает, от нас сейчас госструктура одна требует отправки сообщений некоего протокола "целым кол-вом штук в одном ТСР-пакете и чтоб пакет с начала сообщения начинался". Доводы и убеждения на них не действуют. "Хотим и всё". Приходится через задницу всё делать... G>А как они намерены это проверять?
Снифером, наверное. С подменой понятия "сегмент TCP" на "пакет TCP"
Проверяется-то элементарно. Сама постановка задачи, конечно, идиотская. Не могу даже представить, чем может быть вызвана. И, если уж есть какие-то веские причины, то причем тут TCP? Реализовывали бы уже на UDP или писали бы свой транспортный протокол.
Здравствуйте, Michael Chelnokov, Вы писали:
G>>А как они намерены это проверять?
MC>Снифером, наверное. С подменой понятия "сегмент TCP" на "пакет TCP" MC>Проверяется-то элементарно. Сама постановка задачи, конечно, идиотская. Не могу даже представить, чем может быть вызвана. И, если уж есть какие-то веские причины, то причем тут TCP? Реализовывали бы уже на UDP или писали бы свой транспортный протокол.
Я к тому, что может никто и проверять-то не будет? Раз они сами не знают зачем им это надо ("Хотим и все!")
в борьбе со здравым смыслом победа будет за нами!
Re[18]: Пакеты иногда не приходят на сокет
От:
Аноним
Дата:
05.12.07 15:40
Оценка:
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, Аноним, Вы писали:
А>>Так что если назвать TCP сегмент пакетом искажения смысла не произойдет.
MC>В том-то и дело что происходит искажение смысла. Под "пакетом" люди чаще всего понимают то что получается за один вызов recv/recvfrom
(лично я ни разу не видел на этом форуме другого толкования от людей, пишущих про пакеты в TCP).
Пакетом называется последовательность байт, имеющая определенную структуру — заголовок( данные управляющие передачей ) и данные пользователя (payload).
Пакет — единица передачи данных по сети. Определение пакета не имеет никакого отношения к функциям recv, recvfrom. Также, определение пакета никак не связано c Вашим пониманием "толкования от людей, пишущих про пакеты в TCP" на данном форуме. Пакет это не то что получается за один вызов recv. recv получает данные(набор байт) из сокета. В этом наборе нет никакого заголовка. А вот recvfrom получает даже не пакет, а датаграмму. Опять пользователю возвращаются лишь сами данные и адрес источника.
Посмотрите на использование термина packet применительно к TCP за пределами форума в сети и вы увидите что термин packet также широко используется. При этом никакой неоднозначности не возникает.
MC>>Снифером, наверное. С подменой понятия "сегмент TCP" на "пакет TCP" MC>>Проверяется-то элементарно. Сама постановка задачи, конечно, идиотская. Не могу даже представить, чем может быть вызвана. И, если уж есть какие-то веские причины, то причем тут TCP? Реализовывали бы уже на UDP или писали бы свой транспортный протокол. G>Я к тому, что может никто и проверять-то не будет? Раз они сами не знают зачем им это надо ("Хотим и все!")
Ох, жжоте, ой как жжоте, граждане, муахахахахаха..............................
Чуть из кресла не вывалился от смеха.
Здравствуйте, Unmanaged, Вы писали:
U>Ох, жжоте, ой как жжоте, граждане, муахахахахаха.............................. U>Чуть из кресла не вывалился от смеха. U>А вообще грустно это всё, конечно.
AC>А то блин... Маразм-то крепчает, от нас сейчас госструктура одна требует отправки сообщений некоего протокола "целым кол-вом штук в одном ТСР-пакете и чтоб пакет с начала сообщения начинался". Доводы и убеждения на них не действуют. "Хотим и всё". Приходится через задницу всё делать...
Пересылайте через UDP. А в начале пакете в ASCII кодировке напишите: "ТСР пакет, ГОСТ 793-81"
Всё гораздо хуже. Проверять они это будут 1) сниффером 2) своим кривым приложением.
если в 1м случае мы еще кое-как можем сделать так чтобы пакеты действительно содержали только целые сообщения (хотя и это сверхгеморрой, учитывая что нам это нужно аж под 3мя ОС: pSOS, VxWorks, Linux), то во втором случае засада полная.
Вобщем дело обстоит так: есть у них кривое приложение, которое судя по всему, делает recv() и начинает анализировать пришедшие данные. При этом авторы приложения слабо себе представляли что к чему, и ситуация, когда recv() получает буфер, начинающийся не с начала сообщения (там специальный байтик) вызывает диагностическо-ругательное сообщение и игнорирование полученных данных. А мы получаем замечание от госструктуры что, мол, фигню шлем, и не проходим испытания. Таким образом или мы идем домой или делаем так чтоб работало. Пока что работает. Ни дай бог что нить там на их стороне в TCP стеке перефрагментируется и recv получит опять нецелое сообщение...
Там,в этой госструктуре похоже есть люди, которые понимают что проблема-то в их проложении. Но, дело в том, что это их приложение писала некая израильская компания за кучу бабок. А чтоб исправить косяк хотят, наверное, еще больше. Поэтому решать будем мы, через одно место, зато бесплатно. По тем же причинам, поменять протокол с TCP на UDP уже нельзя. Да и TCP в целом тут подходит лучше, если бы не чьи-то кривые руки.
Сейчас эта самая госструктура собирается вносить данное требование по ТСР-пакетам в официальные тех-условия на протокол. Не ту страну назвали гондурасом...
З.Ы. предлагаю соревновательный конкурс-задачку: как реализовать управление пакетами в рамках стандартного сокетного API.(З.Ы. у нас кое-как, но работает).
AC>З.Ы. предлагаю соревновательный конкурс-задачку: как реализовать управление пакетами в рамках стандартного сокетного API.(З.Ы. у нас кое-как, но работает).
Чо тут думать то? Открываем сырой сокет, лепим пакеты вручную. Работать будет криво, зато проконтроллировать, что данные попадают в пакет целиком элементарно .
Здравствуйте, TarasCo, Вы писали:
TC>Чо тут думать то? Открываем сырой сокет, лепим пакеты вручную. Работать будет криво, зато проконтроллировать, что данные попадают в пакет целиком элементарно .
Под линуксом будет, ага. А pSOS с VxWorks? Фиг там а не raw сокеты, насколько я знаю.
AC>З.Ы. предлагаю соревновательный конкурс-задачку: как реализовать управление пакетами в рамках стандартного сокетного API.(З.Ы. у нас кое-как, но работает).
1. Контролировать чтобы уходящие данные были не слишком большого размера, и посылать их за 1 send
2. Посылать следующий не раньше чем через некоторое время, скажем, 1с.
3. Возможно, TCP_NODELAY включить.
Надежног не будет, но повышается вероятность что будет работать именно так.
Как вариант — ставить у товарищей спец-ретранслятор данных, слать все к нему, а он будет разбивать данные на порции если это необходимо и отправлять порциями на этот сервис локальной машины. Желательно с учетем пп1-2.