На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Переполнение буфера сокета , Как определить переполнение буфера сокета и как с этим грамотно бороть
    Здравствуйте, all!

    Проблема в следующем: приложение получает поток данных по UDP (скорость примерно 300 килобАЙт/сек). Есть сильное подозрение, что несмотря на то, что буфер приемного сокета приложения увеличен до максимума (setsockopt с опцией SO_RCVBUF), буфер все равно переполняется — иногда спустя некоторое время функция recv возвращает -1, а WSAGetLastError = 10055 (No buffer space available). Сокет работает в блокирующем режиме. Скажите, как нужно правильно прореагировать, если буфер сокета переполнился? Есть ли какие-то способы кроме как перезапустить программу или пересоздать сокет?
      Тут может быть несколько возможных версий
      1. Буфер действительно мал - кстати, укажите размер
      2. Приложение медленно освобождает приемный буфер recvfrom() или он очень маленький - а туда должна поместиться вся датаграмма целиком
      3. Cтоит хилая сетевая карта (медленно работает)
      4. Принципиально быстрый UDP-передатчик может задушить медленный приемник
      5. Компу нехватает памяти (много приложений открыто и отсюда нехватка)
      Цитата deadka @
      Скажите, как нужно правильно прореагировать, если буфер сокета переполнился?

      Нужно обработать ошибку - это во первых. А далее можно пересоздать новый сокет в этой же программе и пытаться продолжить - но на это время желательно было бы сервер приостановить. А во вторых - и самых главных - нужен специальный протокол общения с сервером - чтобы корректировать возникающие проблемы - например слать подтверждение на сервер после которого тот шлет повторно.
      Или чтобы сервер не сыпал так быстро - скажем sleep какой между передачами.
      те простого решения может и не быть - надо экспериментировать :)
        Здравствуйте, Oleg2004.
        >Тут может быть несколько возможных версий
        >1. Буфер действительно мал - кстати, укажите размер
        Был стандартный по умолчанию 8192 байта. Поставил 16мб - windows не дает поставить больше.
        Проверял функцией getsockopt.
        >2. Приложение медленно освобождает приемный буфер recvfrom() или он очень маленький - а туда должна поместиться >вся датаграмма целиком
        Размер буфера заведомо (в 100 раз превышает размера датаграммы), датаграмма влезает.
        Насчет медленного освобождения приемного буфера - вот тут может быть... :(
        >3. Cтоит хилая сетевая карта (медленно работает)
        100 мегабит, встроенная в матернику.
        > 4. Принципиально быстрый UDP-передатчик может задушить медленный приемник
        Это да, об этом и речь, вернее о том, как правильно прореагировать.

        Сформулирую так - да, действительно, могут быть такие ситуации, что приемник отрабатывает медленнее, чем источник. ТО есть действительно может быть такая ситуация, что приемный буфер сокета переполнится.
        Мой вопрос скорее к тому - как это четко обнаружить - и как можно корректно разрулить ситуацию.


        Цитата (deadka @ Сегодня, 12:56)
        Скажите, как нужно правильно прореагировать, если буфер сокета переполнился?

        >Нужно обработать ошибку - это во первых.
        А что именно? Вывести лог какой - а как еще?

        >А далее можно пересоздать новый сокет в этой же программе и пытаться продолжить - но на это время желательно >было бы сервер приостановить.
        Увы, не приостановлю - Циска траффик шлет.
        > А во вторых - и самых главных - нужен специальный протокол общения с сервером - чтобы корректировать >возникающие проблемы - например слать подтверждение на сервер после которого тот шлет повторно.
        Здесь данные не столько критичные - потому по UDP и идут. В пределах процента - потери вполне можно стерпеть.

        >Или чтобы сервер не сыпал так быстро - скажем sleep какой между передачами.
        >те простого решения может и не быть - надо экспериментировать

        Увы, тоже не выйдет - realtime.

        Резюме видимо таково, что единственное, что можно сделать - это вывести лог или что там еще, закрыть/открыть сокет?
          M

          deadka, используй, пожалуйста, теги цитат.
            Может еще продумать логику принимающей программы? Например, чтобы она успевала все принимать, создавала уже внутри себя очередь и отдельным потоком ее обрабатывала.

            Можем больше помочь, если раскроешь больше проблему.
              Цитата gruy @
              Может еще продумать логику принимающей программы? Например, чтобы она успевала все принимать, создавала уже внутри себя очередь и отдельным потоком ее обрабатывала.

              Можем больше помочь, если раскроешь больше проблему.

              Спасибо, я сейчас ровно так и делаю - в смысле в два потока - один принимает и кладет в кольцевой буфер, другой уже оттуда берет и делает логику :-). Что касается раскрыть больше проблему - то у меня вопрос - что можно (и нужно) делать если буфер переполнился, и только он. С остальным более-менее понятно как раз.
                Тут уже нужно определить где именно узкое место: сетевая карта (а они в значительной степени различаются между собой), драйвер сетевой карты, проблема в системных вызовах, неоптимизированная программа, в конце концов слабое железо.

                ЗЫ. Случаем не NetFlow идет?
                  Цитата gruy @
                  Тут уже нужно определить где именно узкое место: сетевая карта (а они в значительной степени различаются между собой), драйвер сетевой карты, проблема в системных вызовах, неоптимизированная программа, в конце концов слабое железо.

                  ЗЫ. Случаем не NetFlow идет?

                  Netflow, он самый. УЖ не имеете ли вы случаем опыта написания софта для работы с NetFLow (на программном уровне)?!
                    Разбирал его только ради интереса, соответственно и программа была простенькая, да и поток намного меньший.

                    Но почему не взять уже готовое решение, тем более что есть с открытыми исходниками, например flow-tools.
                      Цитата gruy @
                      Разбирал его только ради интереса, соответственно и программа была простенькая, да и поток намного меньший.

                      Но почему не взять уже готовое решение, тем более что есть с открытыми исходниками, например flow-tools.

                      Пробовал flow-tools. Мощность моего потока - примерно 2мегабит/сек - flow/tools не справляется :(, 20% потерь стабильно.
                        Цитата deadka @
                        Мощность моего потока - примерно 2мегабит/сек

                        Супербыстрый поток!!!(для UDP) Его абсолютно корректно обработать наверно можно только на уровне спецдрайвера - типа виртуального драйвера, заточенного под UDP-поток. Хотя......
                        Ихто его знает <_<
                          Цитата Oleg2004 @
                          Цитата deadka @
                          Мощность моего потока - примерно 2мегабит/сек

                          Супербыстрый поток!!!(для UDP) Его абсолютно корректно обработать наверно можно только на уровне спецдрайвера - типа виртуального драйвера, заточенного под UDP-поток. Хотя......
                          Ихто его знает <_<

                          Ну да, циска собирает траффик с отделений в нескольких городах. Обработать-то можно, знать бы как. Вот и валятся у меня сокеты иногда - с чем и пришел - что делать в этом случае. Всем спасибо за ответы!
                            У самой циски есть возможность распределять потоки по разным коллекторам?
                              Цитата gruy @
                              У самой циски есть возможность распределять потоки по разным коллекторам?

                              Данная циска может слать только в два места ( и то весь поток сразу). С другой стороны на другой машине можно разделять потоки по тому или иному принципу.
                                Т.е. она может один поток сразу на два коллектора посылать? Тогда, в принципе, можно придумать способ сбора и совмещения информации с двух коллекторов, даже если они часть будут пропускать, но есть вероятность что это будут разные пакеты.

                                Хотя, конечно, можно еще поработать над конфигурацией одного коллектора...
                                  Цитата gruy @
                                  Т.е. она может один поток сразу на два коллектора посылать? Тогда, в принципе, можно придумать способ сбора и совмещения информации с двух коллекторов, даже если они часть будут пропускать, но есть вероятность что это будут разные пакеты.

                                  Хотя, конечно, можно еще поработать над конфигурацией одного коллектора...

                                  Конфигурация, как я понял, должна выглядеть примерно так: 1-й поток: данные приходят на коллектор и складываются банарно в некий буфер (большой). 2-й поток уже делает с ними что-нибудь - в базу кладет или еще куда. Иногда еще и третий можно прикрутить - если ему есть чем заняться. Ну и желательно конечно писать не сразу в базу, а сначала в бинарные файлы, а оттуда уже выжимки, отчеты несколькоминутные в базу. А "один коллектор" - это о каком речь идет?
                                  1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0348 ]   [ 14 queries used ]   [ Generated: 9.11.25, 22:42 GMT ]