Russian Qt Forum

Qt => Работа с сетью => Тема начата: alexlogvinenkoit от Май 04, 2012, 15:06



Название: UDP интенсивность отправки данных
Отправлено: 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 итераций и зависает... При чем не кушает оперативу или проц, программа отвечает, но перестают отсылаться пакеты и все)

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

Спасибо!


Название: Re: UDP интенсивность отправки данных
Отправлено: V1KT0P от Май 04, 2012, 15:15
Всем привет!

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

Подскажите, пожалуйста, как можно контролировать интенсивность отсылки данных?
Я бы на твоем месте использовал asio входящий в состав boost.


Название: Re: UDP интенсивность отправки данных
Отправлено: alexlogvinenkoit от Май 04, 2012, 15:22
Вообще левую библиотеку юзать не очень интересно, а IOCP/epoll уже встроены в систему. Полностью асинхронные. Самый крутой пример - nginx, если вот не ошибаюсь 10000 коннектов - пару метров оперативы кушает))

А asio сам контролирует интенсивность передачи/приема?


Название: Re: UDP интенсивность отправки данных
Отправлено: V1KT0P от Май 04, 2012, 15:38
Вообще левую библиотеку юзать не очень интересно, а IOCP/epoll уже встроены в систему. Полностью асинхронные. Самый крутой пример - nginx, если вот не ошибаюсь 10000 коннектов - пару метров оперативы кушает))

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


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


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


Название: Re: UDP интенсивность отправки данных
Отправлено: alexlogvinenkoit от Май 04, 2012, 15:58
Ну если только так... Все равно asio, пока что, остается запасным планом.

А по поводу UDP ничего не скажешь? Вообще в ту сторону рою? Или где-то еще может быть ошибка?


Название: Re: UDP интенсивность отправки данных
Отправлено: V1KT0P от Май 04, 2012, 16:03
Ну если только так... Все равно asio, пока что, остается запасным планом.

А по поводу UDP ничего не скажешь? Вообще в ту сторону рою? Или где-то еще может быть ошибка?
Запусти под отладчиком и при зависании останови прогу и глянь где она застряла. Может что-то в твоей обертке сделано не так.


Название: Re: UDP интенсивность отправки данных
Отправлено: alexlogvinenkoit от Май 04, 2012, 16:31
Ну да, я бы сам не додумался... Суть в том, что в дебаге все работает как часики, если ставить delay - то же самое.
Пока что написал такой тест: 2 сокета, 2 счетчика (2 int переменные). Сокеты отсылают данные много раз, а при получении данных - инкремент своего счетчика. С delay - нормально все, без него - значения счетчиков постоянно разные (иногда даже у 1-го остается нулевым). Ошибок никаких. Вот так)


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


Название: Re: UDP интенсивность отправки данных
Отправлено: alexlogvinenkoit от Май 04, 2012, 16:54
Хорошая идея, но логирование я уже реализовал. Я его специально выключил (оставил только на ошибках), т.к. при включенном логировании эффект такой же, как от delay)))
Просто на вывод сообщения (или даже записи его в файл) тратится время, вот и все)))


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


Название: Re: UDP интенсивность отправки данных
Отправлено: alexlogvinenkoit от Май 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;
    }

}

Вот как-то так.


Название: Re: UDP интенсивность отправки данных
Отправлено: Странник от Май 04, 2012, 17:58
буфера не хватает?


Название: Re: UDP интенсивность отправки данных
Отправлено: alexlogvinenkoit от Май 04, 2012, 18:11
Цитировать
буфера не хватает?
В смысле? Буфера хватает, больше чем надо, тем более, что в IOCP на каждый сокет отдельный буфер. Хотя недавно наткнулся на статейку, как можно сделать одним буфером, как в epoll, но пока что переписывать нет смысла...