Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.79/34: Рейтинг темы: голосов - 34, средняя оценка - 4.79
4 / 4 / 1
Регистрация: 10.07.2011
Сообщений: 52

Задержка пакетов UDP

14.11.2013, 15:34. Показов 6860. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем добрый день,
не нашёл на просторах интернета ответа на свой
вопрос, по этому хочу спросить у вас, надеюсь на ответ.

Принимаю данные по UDP от устройства - самопальной видеокамеры.
Данные отправляются непрерывно, но на стационарных ПК задержка
на приёме минимальная, а вот на ноутбуках Samsung (а возможно и на других)
возникает задержка больше 1 секунды.
Ещё раз раз поясню: устройство отправляет данные в момент Т, а на экране
монитора они отбражаются на стационарном ПК через Т+100мс, а на ноутбуках
через Т+1000мс. Задержка не меняется от времени примерно стабильная.

Принимает ПО на C#, следующим образом:

C#
1
2
3
4
5
6
7
8
9
                int nInData = 0x00;
                int nNetData = UDPClient.Available;
 
                while ((!BreakThread) & (nNetData > 1024) & (pos < (receiveBytes.Length - 1024*1024)))
                    {
                        nInData = UDPClient.Receive(receiveBytes, pos, 1024, SocketFlags.None);
                        nNetData -= 1024;
                        pos += nInData;
                    }
Кстати, забирать из UDPClient кусками больше 1024 не получается, просто не принимает и зависает...
по этому выбираю в цикле кусками по 1024 байта...

Загрузка ПК ПО не более 20%.
Поток данных не более 12Мбайт/с.
Буфер задан, как :
C#
1
2
3
            int BufferSize = 1280 * 1024 * 8 * 16; 
                UDPClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                UDPClient.ReceiveBufferSize = BufferSize;
Что примерно соответствует 160Мбайтам, то есть заведомо больше времени лага...
кажется что и не причём...
Потери пакетов нет, пропусков данных так же нет.
Антивирусы отключены
сетевые карты как на стационарном так и на ноутбуке Realtek GigE

Ну собственно сабж, прошу помощи...

Заранее спасибо!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.11.2013, 15:34
Ответы с готовыми решениями:

Сниффер UDP пакетов
Здравствуйте, нужно написать сниффер, который будет перехватывать только UDP пакеты Начал искать информацию, так понял, что нужно...

Отправка udp sip пакетов .NET 4.5
Возникла проблема, что при попытке отправить SIP сообщения в UDP пакете, SIP часть отправляется как data, в котором просто содержится...

Прием широковещательных UDP пакетов
Делаю следующим образом: public static void ReceiveFrom1() { Socket sock = new...

6
192 / 199 / 82
Регистрация: 11.04.2013
Сообщений: 1,086
18.11.2013, 08:41
Тут дело не в загрузке ПО ПК, а скорее всего в видеокарте ноута, при прочих равных ноут всегда уступает стационарному ПК в производительности
1
4 / 4 / 1
Регистрация: 10.07.2011
Сообщений: 52
21.11.2013, 10:42  [ТС]
Всем привет!
опять же проблема оказалась в реализации StopWatch
(((
может быть кто-то знает как гарантированно измерить
абсолютное время?.
Объясню подробнее, я с помощью StopWatch измеряю интервал
времени равный 35мс, с запасом от 40мс, что соответствует 25Гц,
камера четко со стабильностью 10^-4 выдаёт именно 25Гц видео,
при работе с большинством персональных ПК время измеряется
корректно, буфер не заполняется. При работе с AMD/ATI и вот как оказалось
с ноутом Samsung измеренное время оказывается больше, то есть по факту
не 35мс, а где-то 50мс... буфер переполняется - возникает задержка в буфере.
Опять же повторю вопрос, как измерить абсолютное время в шарпах?...

всем заранее спасибо!
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
21.11.2013, 21:36
Pyhesty, может вы покажете код, как вы используете StopWatch, и мы поищем проблемы в нём. Скорее всего вы что-то делаете не так.
1
4 / 4 / 1
Регистрация: 10.07.2011
Сообщений: 52
21.11.2013, 22:27  [ТС]
спасибо!)
собственно юзаю вот так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
       
 public ConcurrentQueue<sFrame> FrameBuffer;
 private void Parse()
        {
            BreakThread = false;
            sFrame Frame;
            Stopwatch swBuf = new Stopwatch();
            swBuf.Start();
            while (!BreakThread) // && !TimeOut)
            {
                if (FrameBuffer != null)
                {
                    int BuffCount = FrameBuffer.Count;
                    long delay = swBuf.ElapsedMilliseconds;
                    if (((BuffCount > VideoBufferSize) && (delay > 35)) || ((BuffCount > 0) && (delay > 45)))
                        if (FrameBuffer.TryDequeue(out Frame))
                        {
                            swBuf.Restart();
                          //  if (writelog) log.WriteLine("Delay time: " + delay + "  " + BuffCount);
                            DrawFrame(ref Frame);
                            nFrame++;
                        }
                        else  Thread.Sleep(1);
                } else 
                    Thread.Sleep(1);
            }
                
        }
Идея предельно просто - создаётся поток, который мониторит FIFO буферов
кадров FrameBuffer, если в нём есть кадры, и время прошло больше 45мс, то в любом случае
выводим кадр, если время прошло от 35 до 45мс и в буфере есть некоторое количество кадров
больше VideoBufferSize, то так же выводим кадр. В буфере необходимо держать несколько кадров,
на случай лагов сети.
C#
1
  if (writelog) log.WriteLine("Delay time: " + delay + "  " + BuffCount);
позволяет вывести лог и построить диаграмму, на нормальном ПК отклонение в выводе изображения
не превышает 5мс. Если же встречается AMD или такой ноутбук, что у меня, то получается,
что ПК думает, что времени прошло меньше чем нужно и буфер начинает переполнятся,
тк всегда срабатывает условие, ((BuffCount > VideoBufferSize) && (delay > 35)), при том, что
буфер полностью заполнен...
Кадры поступают гарантированно раз в 40мс... Предполагаю, что незаметно для программы
меняется частота процессора и StopWatch не меняет некоторую переменную типа CPU_TICKS.
При этом на своём ПК, запускаю CPU-Z и наблюдаю, что тактовая процессора меняется от 1.6ГГц, до 3.0
и это не сказывается на работе ПО, почему это сказывается на других процессорах, не могу понять.
Прошу помощи, заранее спасибо!
0
0 / 0 / 0
Регистрация: 18.09.2015
Сообщений: 1
16.11.2016, 12:29
та же проблема - не могу обработать звук входящий из УДП вовремя. пакеты приходят со скоростью 30мс, а я их получаю с помощью UDPClient.Receive со скоростью за 100мс и больше, при этом весть остальной код уже давно выключен - тормозит сам класс UDPClient!!!

буду искать ответы, другого выбора у меня нет!
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
26.11.2016, 10:30
При выполнении Thread.Sleep(x) поток отказывается от выделенного ему кванта времени и сможет продолжить работу не раньше чем при следующем запуске системного таймера (Windows system timer).
По умолчанию период системного таймера (timer resolution) равняется 15.6 ms. Но программы могут уменьшать это значение до 1 ms и даже до 0.5 ms.
Поэтому ваша проблема воспроизводится не на всех компьютерах, а только на тех, где этот таймер не установлен на меньший период.
В случае стандартного периода 15.6 ms несмотря на все ваши стремления (Thread.Sleep(1)) значения delay будут в основном такими: 0->15.6 (16)->31.2 (31)->46.8 (47).
А учитывая, что Stopwatch перезапускается после обработки каждого кадра, то ошибка будет постоянно накапливаться.
Самый простой вариант - это установить интервал системного таймера в 1 ms, тогда вся эта колбасня со Thread.Sleep(1) будет работать как положено, с квантованием в 1 ms.
Но я бы попробовал переделать обработку кадров на использование высокоточного WinApi таймера. Средняя частота вызова события этого таймера будет гарантировано 40 ms.

C#
1
2
3
4
5
6
7
            AccurateTimer t = new AccurateTimer(40);
            t.TimerTick += (s, e) =>
            {
                // поместить сюда обработку кадра
            };
 
            t.Start(); // t.Stop() обязательно нужно вызвать при закрытии программы, или когда таймер больше не нужен
Реализация таймера:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  public class AccurateTimer
    {
        private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2);
        private const int TIME_PERIODIC = 1;
        private const int EVENT_TYPE = TIME_PERIODIC;
        [DllImport("winmm.dll")]
        private static extern int timeBeginPeriod(int msec);
        [DllImport("winmm.dll")]
        private static extern int timeEndPeriod(int msec);
        [DllImport("winmm.dll")]
        private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType);
        [DllImport("winmm.dll")]
        private static extern int timeKillEvent(int id);
 
        private int mTimerId;
        private TimerEventDel mHandler;  // NOTE: declare at class scope so garbage collector doesn't release it
 
        public event EventHandler TimerTick;
        private int _interval;
        
        public AccurateTimer(int interval)
        {
            _interval = interval;
        }
 
        public void Start()
        {
            if (mHandler != null)
            {
                throw new InvalidOperationException("Timer have been already started");
            }
 
            timeBeginPeriod(1);
            mHandler = new TimerEventDel(TimerCallback);
            mTimerId = timeSetEvent(_interval, 0, mHandler, IntPtr.Zero, EVENT_TYPE);
        }
 
        public void Stop()
        {
            int err = timeKillEvent(mTimerId);
            timeEndPeriod(1);
            System.Threading.Thread.Sleep(100);// Ensure callbacks are drained
        }
        
        private void TimerCallback(int id, int msg, IntPtr user, int dw1, int dw2)
        {
            var h = TimerTick;
            if (h != null)
            {
                h(this, EventArgs.Empty);
            }
        }
    }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.11.2016, 10:30
Помогаю со студенческими работами здесь

Прием пакетов по UDP
Приветствую. С сетевыми протоколами раньше дела не имел. Начал сразу к практике приступать. Хотел посмотреть, как вообще реализовать...

Потери UDP пакетов
Всем привет. Моя работа заключается в настройке IP_TV. Довольно часто люди жалуются на зависание картинки. Хотелось бы узнать побольше...

Перехват UDP пакетов
Здравствуйте ! Есть два комп'ютера связанные по сети. Программа на первом отправляет некие данные на второй по UDP протоколу. Как...

Потери UDP пакетов
Всем здравствуйте...Столкнулся со следующей проблемой. Попытался передать довольно большой файл по сети UDP пакетами размером в пару сотен...

Прием UDP пакетов
Здравствуйте. Сразу скажу, никогда не имел дело с сокетами, тем более с UDP. Сервер у меня на python и с ним проблем никаких нет, клиент...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru