Переполнение буфера сокета
, Как определить переполнение буфера сокета и как с этим грамотно бороть
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.141] |
|
|
Переполнение буфера сокета
, Как определить переполнение буфера сокета и как с этим грамотно бороть
|
Сообщ.
#1
,
|
|
|
|
Здравствуйте, all!
Проблема в следующем: приложение получает поток данных по UDP (скорость примерно 300 килобАЙт/сек). Есть сильное подозрение, что несмотря на то, что буфер приемного сокета приложения увеличен до максимума (setsockopt с опцией SO_RCVBUF), буфер все равно переполняется — иногда спустя некоторое время функция recv возвращает -1, а WSAGetLastError = 10055 (No buffer space available). Сокет работает в блокирующем режиме. Скажите, как нужно правильно прореагировать, если буфер сокета переполнился? Есть ли какие-то способы кроме как перезапустить программу или пересоздать сокет? |
|
Сообщ.
#2
,
|
|
|
|
Тут может быть несколько возможных версий
1. Буфер действительно мал - кстати, укажите размер 2. Приложение медленно освобождает приемный буфер recvfrom() или он очень маленький - а туда должна поместиться вся датаграмма целиком 3. Cтоит хилая сетевая карта (медленно работает) 4. Принципиально быстрый UDP-передатчик может задушить медленный приемник 5. Компу нехватает памяти (много приложений открыто и отсюда нехватка) Цитата deadka @ Скажите, как нужно правильно прореагировать, если буфер сокета переполнился? Нужно обработать ошибку - это во первых. А далее можно пересоздать новый сокет в этой же программе и пытаться продолжить - но на это время желательно было бы сервер приостановить. А во вторых - и самых главных - нужен специальный протокол общения с сервером - чтобы корректировать возникающие проблемы - например слать подтверждение на сервер после которого тот шлет повторно. Или чтобы сервер не сыпал так быстро - скажем sleep какой между передачами. те простого решения может и не быть - надо экспериментировать |
|
Сообщ.
#3
,
|
|
|
|
Здравствуйте, Oleg2004.
>Тут может быть несколько возможных версий >1. Буфер действительно мал - кстати, укажите размер Был стандартный по умолчанию 8192 байта. Поставил 16мб - windows не дает поставить больше. Проверял функцией getsockopt. >2. Приложение медленно освобождает приемный буфер recvfrom() или он очень маленький - а туда должна поместиться >вся датаграмма целиком Размер буфера заведомо (в 100 раз превышает размера датаграммы), датаграмма влезает. Насчет медленного освобождения приемного буфера - вот тут может быть... ![]() >3. Cтоит хилая сетевая карта (медленно работает) 100 мегабит, встроенная в матернику. > 4. Принципиально быстрый UDP-передатчик может задушить медленный приемник Это да, об этом и речь, вернее о том, как правильно прореагировать. Сформулирую так - да, действительно, могут быть такие ситуации, что приемник отрабатывает медленнее, чем источник. ТО есть действительно может быть такая ситуация, что приемный буфер сокета переполнится. Мой вопрос скорее к тому - как это четко обнаружить - и как можно корректно разрулить ситуацию. Цитата (deadka @ Сегодня, 12:56) Скажите, как нужно правильно прореагировать, если буфер сокета переполнился? >Нужно обработать ошибку - это во первых. А что именно? Вывести лог какой - а как еще? >А далее можно пересоздать новый сокет в этой же программе и пытаться продолжить - но на это время желательно >было бы сервер приостановить. Увы, не приостановлю - Циска траффик шлет. > А во вторых - и самых главных - нужен специальный протокол общения с сервером - чтобы корректировать >возникающие проблемы - например слать подтверждение на сервер после которого тот шлет повторно. Здесь данные не столько критичные - потому по UDP и идут. В пределах процента - потери вполне можно стерпеть. >Или чтобы сервер не сыпал так быстро - скажем sleep какой между передачами. >те простого решения может и не быть - надо экспериментировать Увы, тоже не выйдет - realtime. Резюме видимо таково, что единственное, что можно сделать - это вывести лог или что там еще, закрыть/открыть сокет? |
|
Сообщ.
#4
,
|
|
|
|
M deadka, используй, пожалуйста, теги цитат. |
|
Сообщ.
#5
,
|
|
|
|
Может еще продумать логику принимающей программы? Например, чтобы она успевала все принимать, создавала уже внутри себя очередь и отдельным потоком ее обрабатывала.
Можем больше помочь, если раскроешь больше проблему. |
|
Сообщ.
#6
,
|
|
|
|
Цитата gruy @ Может еще продумать логику принимающей программы? Например, чтобы она успевала все принимать, создавала уже внутри себя очередь и отдельным потоком ее обрабатывала. Можем больше помочь, если раскроешь больше проблему. Спасибо, я сейчас ровно так и делаю - в смысле в два потока - один принимает и кладет в кольцевой буфер, другой уже оттуда берет и делает логику :-). Что касается раскрыть больше проблему - то у меня вопрос - что можно (и нужно) делать если буфер переполнился, и только он. С остальным более-менее понятно как раз. |
|
Сообщ.
#7
,
|
|
|
|
Тут уже нужно определить где именно узкое место: сетевая карта (а они в значительной степени различаются между собой), драйвер сетевой карты, проблема в системных вызовах, неоптимизированная программа, в конце концов слабое железо.
ЗЫ. Случаем не NetFlow идет? |
|
Сообщ.
#8
,
|
|
|
|
Цитата gruy @ Тут уже нужно определить где именно узкое место: сетевая карта (а они в значительной степени различаются между собой), драйвер сетевой карты, проблема в системных вызовах, неоптимизированная программа, в конце концов слабое железо. ЗЫ. Случаем не NetFlow идет? Netflow, он самый. УЖ не имеете ли вы случаем опыта написания софта для работы с NetFLow (на программном уровне)?! |
|
Сообщ.
#9
,
|
|
|
|
Разбирал его только ради интереса, соответственно и программа была простенькая, да и поток намного меньший.
Но почему не взять уже готовое решение, тем более что есть с открытыми исходниками, например flow-tools. |
|
Сообщ.
#10
,
|
|
|
|
Цитата gruy @ Разбирал его только ради интереса, соответственно и программа была простенькая, да и поток намного меньший. Но почему не взять уже готовое решение, тем более что есть с открытыми исходниками, например flow-tools. Пробовал flow-tools. Мощность моего потока - примерно 2мегабит/сек - flow/tools не справляется , 20% потерь стабильно. |
|
Сообщ.
#11
,
|
|
|
|
Цитата deadka @ Мощность моего потока - примерно 2мегабит/сек Супербыстрый поток!!!(для UDP) Его абсолютно корректно обработать наверно можно только на уровне спецдрайвера - типа виртуального драйвера, заточенного под UDP-поток. Хотя...... Ихто его знает |
|
Сообщ.
#12
,
|
|
|
|
Цитата Oleg2004 @ Цитата deadka @ Мощность моего потока - примерно 2мегабит/сек Супербыстрый поток!!!(для UDP) Его абсолютно корректно обработать наверно можно только на уровне спецдрайвера - типа виртуального драйвера, заточенного под UDP-поток. Хотя...... Ихто его знает ![]() Ну да, циска собирает траффик с отделений в нескольких городах. Обработать-то можно, знать бы как. Вот и валятся у меня сокеты иногда - с чем и пришел - что делать в этом случае. Всем спасибо за ответы! |
|
Сообщ.
#13
,
|
|
|
|
У самой циски есть возможность распределять потоки по разным коллекторам?
|
|
Сообщ.
#14
,
|
|
|
|
Цитата gruy @ У самой циски есть возможность распределять потоки по разным коллекторам? Данная циска может слать только в два места ( и то весь поток сразу). С другой стороны на другой машине можно разделять потоки по тому или иному принципу. |
|
Сообщ.
#15
,
|
|
|
|
Т.е. она может один поток сразу на два коллектора посылать? Тогда, в принципе, можно придумать способ сбора и совмещения информации с двух коллекторов, даже если они часть будут пропускать, но есть вероятность что это будут разные пакеты.
Хотя, конечно, можно еще поработать над конфигурацией одного коллектора... |
|
Сообщ.
#16
,
|
|
|
|
Цитата gruy @ Т.е. она может один поток сразу на два коллектора посылать? Тогда, в принципе, можно придумать способ сбора и совмещения информации с двух коллекторов, даже если они часть будут пропускать, но есть вероятность что это будут разные пакеты. Хотя, конечно, можно еще поработать над конфигурацией одного коллектора... Конфигурация, как я понял, должна выглядеть примерно так: 1-й поток: данные приходят на коллектор и складываются банарно в некий буфер (большой). 2-й поток уже делает с ними что-нибудь - в базу кладет или еще куда. Иногда еще и третий можно прикрутить - если ему есть чем заняться. Ну и желательно конечно писать не сразу в базу, а сначала в бинарные файлы, а оттуда уже выжимки, отчеты несколькоминутные в базу. А "один коллектор" - это о каком речь идет? |