Russian Qt Forum
Ноябрь 23, 2024, 20:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: UDP интенсивность отправки данных  (Прочитано 10192 раз)
alexlogvinenkoit
Гость
« : Май 04, 2012, 15:06 »

Всем привет!

Пишу приложение (не Qt, чистый С++), суть в чем: асинхронный сервер и клиент (Windows - IOCP, Linux - epoll), есть слой, который разбивает большие объемы данных на более мелкие (пока что константа 1000 байт) и сервер отсылает данные, а клиент принимает и склеивает.

При отсылке данных использую цикл
Код:
//UdpSocket - мой класс, простая обертка над сокетами
void Send(UdpSocket *to, uint8_t *data, ssize_t size)
{
    int len = 1000;
    int seek = 0;
    while(seek != size)
    {
        udpSocket->SendTo(to, &data[seek], len);
        seek += len;
        // HERE GOES DELAY
    }
}

Там, где комментарий "HERE GORES DELAY", ставлю какую-либо задержку - и все работает замечательно, но без задержки проходит около 10 итераций и зависает... При чем не кушает оперативу или проц, программа отвечает, но перестают отсылаться пакеты и все)

Подскажите, пожалуйста, как можно контролировать интенсивность отсылки данных?

Спасибо!
Записан
V1KT0P
Гость
« Ответ #1 : Май 04, 2012, 15:15 »

Всем привет!

Пишу приложение (не Qt, чистый С++), суть в чем: асинхронный сервер и клиент (Windows - IOCP, Linux - epoll), есть слой, который разбивает большие объемы данных на более мелкие (пока что константа 1000 байт) и сервер отсылает данные, а клиент принимает и склеивает.

Подскажите, пожалуйста, как можно контролировать интенсивность отсылки данных?
Я бы на твоем месте использовал asio входящий в состав boost.
Записан
alexlogvinenkoit
Гость
« Ответ #2 : Май 04, 2012, 15:22 »

Вообще левую библиотеку юзать не очень интересно, а IOCP/epoll уже встроены в систему. Полностью асинхронные. Самый крутой пример - nginx, если вот не ошибаюсь 10000 коннектов - пару метров оперативы кушает))

А asio сам контролирует интенсивность передачи/приема?
Записан
V1KT0P
Гость
« Ответ #3 : Май 04, 2012, 15:38 »

Вообще левую библиотеку юзать не очень интересно, а IOCP/epoll уже встроены в систему. Полностью асинхронные. Самый крутой пример - nginx, если вот не ошибаюсь 10000 коннектов - пару метров оперативы кушает))

А asio сам контролирует интенсивность передачи/приема?
Ну дык asio использует poll, select, epoll, eventfd, kqueue, IOCP. Можно использовать как асинхронные так и синхронные операции.
Врятли там есть контроль интенсивности, но легко делается самому. Либо по таймеру посылаем асинхронную передачу, либо в цикле синхронную передачу.
Например банально в треде который режет на мелкие куски посылать события треду который отсылает. А в нем считать время отправки, вычитать из времени задержки и засыпать на получившееся время. Затем выходить из функции и сразу же происходит следующее событие. И т.д. Будет работать как часы. Вариантов как это сделать на asio много.
Записан
alexlogvinenkoit
Гость
« Ответ #4 : Май 04, 2012, 15:47 »

Ну и толку от этого asio, если все равно расчет интенсивности отправки нужно делать самому? Синхронные операции никак не подходят, теряется смысл приложения. Асинхронности я уже добился, так что asio отменяется)
Тут вопрос в самом UDP протоколе: видимо нельзя тупо слать пакеты без остановки, нужно какой-то delay, но вот как его рассчитать? У меня на машине проходит 10 раз цикл, не факт, что на любой машине будет так же. А если каждый раз после отправки вызывать delay - картинка 64кб отсылается секунд 20, не вариант)))
Записан
V1KT0P
Гость
« Ответ #5 : Май 04, 2012, 15:54 »

Ну и толку от этого asio, если все равно расчет интенсивности отправки нужно делать самому? Синхронные операции никак не подходят, теряется смысл приложения. Асинхронности я уже добился, так что asio отменяется)
Тут вопрос в самом UDP протоколе: видимо нельзя тупо слать пакеты без остановки, нужно какой-то delay, но вот как его рассчитать? У меня на машине проходит 10 раз цикл, не факт, что на любой машине будет так же. А если каждый раз после отправки вызывать delay - картинка 64кб отсылается секунд 20, не вариант)))
Ну вот а используй ты asio он бы сам позаботился о том когда можно отсылать следующий кусок. Если например задержка нужна минимальная но каждый пакет должен весить только 1000 байт, то тут вообще проще простого. Тупо при разбивке посылать сигналы на отправку пакета и все дальше asio сам разберется с тем как быстрее их отправить.
Записан
alexlogvinenkoit
Гость
« Ответ #6 : Май 04, 2012, 15:58 »

Ну если только так... Все равно asio, пока что, остается запасным планом.

А по поводу UDP ничего не скажешь? Вообще в ту сторону рою? Или где-то еще может быть ошибка?
Записан
V1KT0P
Гость
« Ответ #7 : Май 04, 2012, 16:03 »

Ну если только так... Все равно asio, пока что, остается запасным планом.

А по поводу UDP ничего не скажешь? Вообще в ту сторону рою? Или где-то еще может быть ошибка?
Запусти под отладчиком и при зависании останови прогу и глянь где она застряла. Может что-то в твоей обертке сделано не так.
Записан
alexlogvinenkoit
Гость
« Ответ #8 : Май 04, 2012, 16:31 »

Ну да, я бы сам не додумался... Суть в том, что в дебаге все работает как часики, если ставить delay - то же самое.
Пока что написал такой тест: 2 сокета, 2 счетчика (2 int переменные). Сокеты отсылают данные много раз, а при получении данных - инкремент своего счетчика. С delay - нормально все, без него - значения счетчиков постоянно разные (иногда даже у 1-го остается нулевым). Ошибок никаких. Вот так)
Записан
V1KT0P
Гость
« Ответ #9 : Май 04, 2012, 16:37 »

Ну да, я бы сам не додумался... Суть в том, что в дебаге все работает как часики, если ставить delay - то же самое.
Пока что написал такой тест: 2 сокета, 2 счетчика (2 int переменные). Сокеты отсылают данные много раз, а при получении данных - инкремент своего счетчика. С delay - нормально все, без него - значения счетчиков постоянно разные (иногда даже у 1-го остается нулевым). Ошибок никаких. Вот так)
Да, бывает так что дебажные и релизные версии работают по разному, тогда можно использовать проверенный способ: логирование. Так как у тебя после 10-ти итераций зависает, то сделай 20-ть и полное логирование. При входе в функцию - запись в лог, при выполнении действия - запись в лог результат и т.д.
Записан
alexlogvinenkoit
Гость
« Ответ #10 : Май 04, 2012, 16:54 »

Хорошая идея, но логирование я уже реализовал. Я его специально выключил (оставил только на ошибках), т.к. при включенном логировании эффект такой же, как от delay)))
Просто на вывод сообщения (или даже записи его в файл) тратится время, вот и все)))
Записан
V1KT0P
Гость
« Ответ #11 : Май 04, 2012, 17:00 »

Хорошая идея, но логирование я уже реализовал. Я его специально выключил (оставил только на ошибках), т.к. при включенном логировании эффект такой же, как от delay)))
Просто на вывод сообщения (или даже записи его в файл) тратится время, вот и все)))
Ну тогда выложи минимальный код или больше кода, а то по тем строчка что есть сказать что-то вообще нереально.
Записан
alexlogvinenkoit
Гость
« Ответ #12 : Май 04, 2012, 17:36 »

Обнаружил, что проблема не в отсылке данных, а в получении (скорее всего)
Получаю данные через IOCP:
Код:
void Loop()
{
    /* Все переменные объявлены в классе, проинициализированы ранее */
    if(!GetQueuedCompletionStatus(_main_io, &dwBytes, &key, (LPOVERLAPPED *)&lpOverlapped, INFINITE))
    {
        Log("Error!"); //Тоже отдельная функция
        return;
    }

    /* ... */

    UdpSocket *udpSocket= (UdpSocket *)lpOverlapper->pData;

    /* ... */

    //Вызываю событие (тоже собственного писания)
    while(WSARecvFrom(udpSocket->_sock, &udpSocket->_wsaBuf, 1, &dwBytes, &udpSocket->_socketFlags,
(sockaddr *)&udpSocket->_addr, &udpSocket->_len, &udpSocket->_wsaOverlapped, 0) == 0)
    {
udpSocket->OnRecvFrom((uint8_t *)udpSocket->_wsaBuf.buf, (int &)dwBytes,
(sockaddr *)&udpSocket->_addr, udpSocket->_len);
    }
   
    if(WSAGetLastError() != WSA_IO_PENDING)
    {
Log("Error: WSAGetLastError() != WSA_IO_PENDING = %i", WSAGetLastError());
return;
    }

}

Вот как-то так.
Записан
Странник
Гость
« Ответ #13 : Май 04, 2012, 17:58 »

буфера не хватает?
Записан
alexlogvinenkoit
Гость
« Ответ #14 : Май 04, 2012, 18:11 »

Цитировать
буфера не хватает?
В смысле? Буфера хватает, больше чем надо, тем более, что в IOCP на каждый сокет отдельный буфер. Хотя недавно наткнулся на статейку, как можно сделать одним буфером, как в epoll, но пока что переписывать нет смысла...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.084 секунд. Запросов: 21.