У меня есть проблема, которую я действительно не знаю, как решить. У меня есть программа, которая мультиплексирует несколько соединений. Эти соединения одновременно получают потоковые данные. Мне пришлось настраивать неблокирующие сокеты, поскольку потоки имеют разные битрейты. Теперь то, что я на самом деле делал, это сохранить эти сокеты в массиве, проходящем через них, и обнаружить с помощью select, если есть данные для чтения и обработки следующего элемента в массиве, если нет. Он работает очень хорошо, за исключением того факта, что процессор всегда на 100%. На самом деле, если в какой-то момент нет ничего, что можно было бы прочитать из любого сокета, он все равно будет зацикливаться. Я действительно не знаю, как можно было бы заблокировать цикл всякий раз, когда никакие данные не доступны ни в одном сокете и просто продолжаются, когда есть данные. Я думаю, что это может быть решение, но я не вижу, как я могу это сделать. Программа должна быть очень отзывчивой, хотя, поскольку она является рекордером потока UDP, и если она блокируется слишком долго, это приведет к задержкам в файле.Как избежать цикла занятости в конкретном случае
Благодарю вас.
PS: Просто для информации, я все еще участвую, поэтому, пожалуйста, не обвиняйте меня, даже если решение может быть очевидным.
EDIT:
вот некоторые псевдо-код:
Когда запрос записи приходит, создать новое подключение и подключиться к адресу потока. Если это удастся, я построю свою fdset используя следующую функцию:
build_fdset()
{
int ii;
/* */
FD_ZERO(&fdset);
/* */
for (ii = 0; ii < max; ii++)
{
if (astRecorder[ii].bUsed != FALSE && astRecorder[ii].socket != INVALID_SOCKET)
{
FD_SET(astRecorder[ii].socket,&fdset);
/* */
if (astRecorder[ii].socket > maxSocket)
maxSocket = astRecorder[ii].socket;
}
}
}
Затем цикл обработки соединений:
main_loop()
{
struct timeval timeout;
/* */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* */
for (;;)
{
memcpy(&fdset_cpy,&fdset,sizeof(fdset));
int ret = select((maxSocket + 1) , &fdset_cpy, NULL, NULL, &timeout);
if (iSelectRet <= 0)
continue;
else
{
int ii;
for(ii = 0; ii < max; ii++)
{
if ((recorders[ii].bUsed) && (FD_ISSET(recorders[ii].socket, &fdset_cpy)))
{
/* receive from socket */
/* handle received data */
}
}
}
}
}
ПРОБЛЕМА: Когда я установил таймаут timeout.tv_sec = 1 timeout.tv_usec = 0 все работает отлично, но я получаю 100% использование ЦП! Когда я даю NULL как тайм-аут, программа блокирует select(), хотя есть данные о сокетах.
РЕШЕНИЕ:
Ну, я наконец-то нашел ошибку! В приведенном выше коде я устанавливаю значения тайм-аута только один раз перед основным циклом. Проблема в том, что для fdset структура тайм-аута изменяется функцией select(). Таким образом, после выбора первого правильного тайм-аута структура тайм-аута изменяется функцией select() и устанавливается в 0. Это приводит к 0 таймауту, поэтому проблема заключается в том, что в следующий раз, когда цикл попадает в функцию выбора, к выбору 0 !!!
Большое спасибо тем, кто пытался помочь! Я его оцениваю =)
Кроме того, что вы используете 'fd_setFlag' в' build_fdset' и 'fdset' в' main_loop', я не вижу ничего неправильного с вашим кодом. –
Самое смешное, что в исходном коде есть функция fdset в обеих функциях. Я немного изменил код, чтобы опубликовать его здесь, и забыл переименовать fd_setFlag в верхней функции. Так что это не ошибка! – gekod
Я просто не понимаю, почему он блокирует, если я установил тайм-аут в NULL – gekod