На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
    > send udp - ICMP error..
      Вопрос таков.
      Есть сервер, с которого к клиенту валит трафик по UDP
      Банальным sendto
      ExpandedWrap disabled
        res = ::sendto(socket, data, data_length, 0, reinterpret_cast<sockaddr*>(&dst), sizeof(dst));

      идет передача, sendto возвращает количество байт, все шоколадно.
      Далее. Делаем клиенту kill -9
      Смотрим на происходящее в канале сниффером и наблюдаем, что трафик продолжает идти..
      Но при этом (внимание!!) С маршрутизатора, а говоря проще с моего мирового айпишника на мой локальный (192.168 ... ) валит ICMP трафик,
      Цитата
      Internet Control Message Protocol
      Type: 3 (Destination unreachable)
      Code: 3 (Port unreachable)

      при этом sendto отчитывается о том что у него все нормально и вся дата отправляется в полном объеме,
      errno тоже success.
      Как ловить событие отваливания клиента ?
      Да, все безобразие происходит на ubuntu server
        Цитата nemez @
        Как ловить событие отваливания клиента ?
        Да, все безобразие происходит на ubuntu server

        Это же UDP, там нет соединения, подтверждения доставки, периодической проверки связи и т.д.
        Так что надо вручную реализовать подтверждение доставки, либо, если допустима потеря нескольких пакетов, сделать контрольные проверочные пакеты периодические, на которые от клиента должен будет прийти ответ.
          Да ладно нету контроля
          вот дамп
          http://s019.radikal.ru/i618/1406/48/ef41ebe48822.jpg
          сверху UDP трафик, снизу - ICMP датаграмма, которая каждый из пакетов, отправляемых в никуда, дублирует вместе с заголовком.
          Система об этом знает и сокеты должны реагировать
          Сообщение отредактировано: nemez -
            Цитата nemez @
            сверху UDP трафик

            Идущий до маршрутизатора, который дальше его не переправляет, т.к. некуда, но никак не информирует отправляющую сторону, т.к. протокол не обязывает.

            Цитата nemez @
            снизу - ICMP датаграмма

            Не имеющая к UDP протоколу никакого отношения :)

            Цитата nemez @
            Система об этом знает и сокеты должны реагировать

            Система и сокеты не должны реагировать, т.к. UDP - протокол без подтверждения, контроля очерёдности и установления соединения.

            Добавлено
            Цитата Хрен @
            Идущий до маршрутизатора, который дальше его не переправляет, т.к. некуда, но никак не информирует отправляющую сторону, т.к. протокол не обязывает.

            Тут ошибся немного. ICMP приходит отправляющей стороне как информирование о недоступности адресата, но ICMP не попадает на UDP'шный сокет, т.к. он не имеет к нему никакого отношения.

            Добавлено
            Если помнишь, в асько-клиентах (в частности в Миранде) был флажок "посылать контрольные пакеты серверу". Если его не установить, то клиент очень долго после фактического дисконнекта мог не знать о пропаже сервера и слать сообщения вникуда. Естественно, после этого они пропадали. Собственно, это из той же оперы - ICQ работает поверх UDP протокола.
              Цитата
              Не имеющая к UDP протоколу никакого отношения

              еще и как имеющая - по крайней мере заголовок исходного UDP пакета в ней присутствует!
              Цитата
              но ICMP не попадает на UDP'шный сокет

              а ему туда попадать не надо - по факту таких передач должен быть получен код возврата соответствующий и при помощи errno получить код ошибки, который скажет, что ошибка либо в отвале клиента, либо во фрагментации, либо закрытом порту.
              Если такой трафик пришел, то сокет должен эту тему отработать. По крайней мере для этого есть все предпосылки.
              Да и на худой конец можно подвязать libpcap или некую ерунду на raw sockets, и это событие перехватить.
              Но хочется все сделать через систему. Только не знаю как.

              Добавлено
              Цитата
              асько-клиентах (в частности в Миранде)

              ну это совсем не показатель - их писали кто попало левой ногой. Потому эта вся аська и накрылась медным тазом
                и вот что пишет великая камасутра

                Цитата
                SO_BSDCOMPAT
                Enable BSD bug-to-bug compatibility. This is used by the UDP protocol module in Linux 2.0
                and 2.2. If enabled ICMP errors received for a UDP socket will not be passed to the user
                program.
                In later kernel versions, support for this option has been phased out: Linux 2.4
                silently ignores it, and Linux 2.6 generates a kernel warning (printk()) if a program uses
                this option. Linux 2.0 also enabled BSD bug-to-bug compatibility options (random header
                changing, skipping of the broadcast flag) for raw sockets with this option, but that was
                removed in Linux 2.2.
                  Цитата nemez @
                  Если такой трафик пришел, то сокет должен эту тему отработать. По крайней мере для этого есть все предпосылки.

                  Специально полистал первоначальный (1981 год) стандарт на эту тему. Именно первоначальный, т.к. сокеты были сделаны в 1983-м, и с того времени не менялись.
                  Дык вот...

                  Цитата
                  If, according to the information in the gateway's routing tables, the network specified in the internet destination field of a datagram is unreachable, e.g., the distance to the network is infinity, the gateway may send a destination unreachable message to the internet source host of the datagram. In addition, in some networks, the gateway may be able to determine if the internet destination host is unreachable. Gateways in these networks may send destination unreachable messages to the source host when the destination host is unreachable.

                  If, in the destination host, the IP module cannot deliver the datagram because the indicated protocol module or process port is not active, the destination host may send a destination unreachable message to the source host.

                  Another case is when a datagram must be fragmented to be forwarded by a gateway yet the Don't Fragment flag is on. In this case the gateway must discard the datagram and may return a destination unreachable message.


                  Вобщем, в этой версии маршрутизаторы не обязывают слать это подтверждение. Только уже позже, когда API сокетов было сформировано, "may" заменили на "should", а потом уже и на "must". Скорее всего, поэтому они и не умеют определять без ядерных костылей, о которых ты написал в последнем посте.
                  Но я смотрю, поведение этого костыля меняется от версии к версии ядра, не понятно вообще, как оно ведёт себя в 3-й версии, и уж тем более это сделает твою прогу непереносимой на другие платформы. Так что я бы эту опцию не использовал, а добавил в протокол периодические проверочные посылки.

                  Цитата nemez @
                  ну это совсем не показатель - их писали кто попало левой ногой. Потому эта вся аська и накрылась медным тазом

                  Аська накрылась не поэтому :)
                    Во первых по поводу kill-9
                    Смотрите здесь
                    Не рекомендуют. Но это по большому счету к проблеме мало.
                    Цитата Хрен @
                    ICMP приходит отправляющей стороне как информирование о недоступности адресата, но ICMP не попадает на UDP'шный сокет, т.к. он не имеет к нему никакого отношения.

                    Совершенно справедливо. ICMP - к UDP-сокету не имеет никакого отношения.
                    Если нет RAW-сокета, куда модуль ICMP может послать свой пакет, то его путь заканчивается в стеке на сетевом уровне.
                    Цитата nemez @
                    Если такой трафик пришел, то сокет должен эту тему отработать. По крайней мере для этого есть все предпосылки.

                    Ваш UDP сокет описан как SOCK_DGRAM...
                    И никакого отношения к IPPROTO_ICMP

                    Ну а по сути - Хрен совершенно прав - это UDP, и коль скоро вы убили клиента - серверу это по барабану. Пока он не закончит отсылку своего буфера - он будет слать свои пакеты "На деревню к дедущке"
                      Цитата
                      Ваш UDP сокет описан как SOCK_DGRAM...
                      И никакого отношения к IPPROTO_ICMP

                      имеет, при том самое непосредственное!

                      RFC 792 говорит нам что:


                      Type | Code | Checksum |
                      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                      | unused |
                      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                      | Internet Header + 64 bits of Original Data Datagra

                      что в свою очередь обозначает что на каждый такой пакет следует ICMP датаграмма с оригинальным заголовком.
                      Получив такую датаграмму, система знает номера портов и говорит сокету о том что с передачей происходит фигня.
                      Тот в свою очередь при send получает код ошибки и говорит юзеру что connection reset by peer.
                        Цитата nemez @
                        Type | Code | Checksum |
                        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                        | unused |
                        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                        | Internet Header + 64 bits of Original Data Datagra


                        Это формат ICMP пакета. Причём тут UDP? И да, ICMP - это датаграммы. И да, на ICMP запрос приходит ответ с теми же данными, которые были отправлены. И да, с ICMP работает совсем другой тип сокета.
                        Сообщение отредактировано: Хрен -
                          Цитата nemez @
                          | Internet Header + 64 bits of Original Data Datagra
                          что в свою очередь обозначает что на каждый такой пакет следует ICMP датаграмма с оригинальным заголовком.
                          Получив такую датаграмму, система знает номера портов и говорит сокету о том что с передачей происходит фигня.

                          Не совсем так.
                          Сообщение ICMP получает сетевой уровень - т.е. модуль ICMP
                          Анализируя 64 бита, которые несет в себе ICMP-пакет, система знает - какому приложению послать сответствующее оповещение. Приложению....а не сокету.

                          Цитата
                          Тот в свою очередь при send получает код ошибки и говорит юзеру что connection reset by peer.

                          Нет в UDP соединения, а потому нет и "connection reset by peer"
                            Цитата
                            Это формат ICMP пакета. Причём тут UDP?

                            Internet Header + 64 bits of Original Data Datagram - туда помещается UDP заголовок
                            При этом имеем цепочку. Датаграмму ICMP - Заголовок IP - Заголовок UDP.
                            Для каждого пакета, отправленного в никуда. Можно было бы говорить что UDP ни при чем, но его заголовок содержится в ICMP датаграмме. Это ЖЖЖЖЖЖ неспроста!

                            Цитата
                            Анализируя 64 бита, которые несет в себе ICMP-пакет, система знает - какому приложению послать сответствующее оповещение. Приложению....а не сокету.

                            а как получить это оповещение?

                            Добавлено
                            Цитата
                            Нет в UDP соединения, а потому нет и "connection reset by peer"

                            зато есть "port unreachable" и кстати событие "connection reset by peer" в TCP отрабатывается именно таким способом - через ICMP
                            Сообщение отредактировано: nemez -
                              Цитата nemez @
                              туда помещается UDP заголовок

                              Он туда помещается не по стандарту, и помещает его туда роутер. Когда ICMP ответ приходит на отправляющую сторону, он не поступает на сокет, т.к. UDP и ICMP - это разные протоколы, которые инкапсулируются внутрь IP, они между собой никак не связаны на уровне сокетов.

                              Цитата nemez @
                              Почему их не отлавливает система, хотя она это делать обязана судя по мануалам?

                              С этого места поподробнее. Что за мануалы? Желаю лицезреть :)
                                http://man7.org/linux/man-pages/man7/socket.7.html
                                читать там где про SO_BSDCOMPAT
                                  Цитата nemez @
                                  читать там где про SO_BSDCOMPAT

                                  Повторюсь:
                                  Цитата Хрен @
                                  поведение этого костыля меняется от версии к версии ядра, не понятно вообще, как оно ведёт себя в 3-й версии, и уж тем более это сделает твою прогу непереносимой на другие платформы.

                                  Т.е. в линуксе решили пойти против абстрагирования двух независимых протоколов и совместить их в этом плане на уровне сокетов. Но, как видно из цитаты
                                  Цитата
                                  In later kernel versions, support for this option has been phased out: Linux 2.4 silently ignores it, and Linux 2.6 generates a kernel warning (printk()) if a program uses this option.

                                  эта фича в том виде, который именно тебе нужен, продержалась совсем недолго. Позже её свели просто на уровень ворнингов. Поэтому да, ты можешь заюзать эту опцию, если согласен, что твой софт сможет быть использован только на линуксе с ядром версии 2.2.
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0.0934 ]   [ 16 queries used ]   [ Generated: 4.07.26, 04:24 GMT ]