The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Проблема с сокетами и select"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Проблема с сокетами и select"  
Сообщение от ufobject email(??) on 20-Июн-06, 13:04 
Привет All!
У меня возникла одна непонятная для меня совершенно проблема... Функция select почему-то отказывается принимать нормально запрос от клиента на слушающий сокет, вернее не срабатывает на событие коннекта. Объясню подробнее:
Мне надо слушать 2 порта на приложении - сервер. Первый клиент будет конектиться на порт 3001 а второй на порт 3002 (vmctrl). Я пишу следующий код:
listener_for_client = vm_listenersock(true,3001);
listener_for_vmctrl = vm_listenersock(true,3002);
Функция vm_listenersock открывает неблокирующий сокет с указанным ей слушающим портом.
Далее выкладываю код цикла обработки:


    set<int> clients;
    clients.clear();
    
            
    while(1)
    {
    //Заполняем множество сокетов
    fd_set readset;
    FD_ZERO(&readset);
    FD_SET(listener_for_vmctrl, &readset);
    FD_SET(listener_for_client, &readset);
    
    //Ждем события в одном из сокетов
    mx = max(listener_for_vmctrl, *max_element(clients.begin(), clients.end()));
    select(mx+1, &readset, NULL, NULL, NULL);
    if(FD_ISSET(listener_for_vmctrl, &readset))
    {
        printf ("I recive connection from vmctrl...\n");
        sock_vmctrl = accept(listener_for_client, NULL, NULL);
        if (sock_vmctrl < 0)
        {
        perror("accept");
        exit(3);
        }
        
        clients.insert(sock_vmctrl);
    }

    if(FD_ISSET(listener_for_client, &readset))
    {
        printf ("I recive connection from client...\n");
        sock_client = accept(listener_for_client, NULL, NULL);
        if (sock_client < 0)
        {
        perror("accept");
        exit(3);
        }
                
        clients.insert(sock_client);
    }
    }

И вот в чем сам фокус!! Если я в инструкции
mx = max(listener_for_vmctrl, *max_element(clients.begin(), clients.end()));
меняю listener_for_vmctrl  на listener_for_client, то select на коннекты vmctrl вообще не реагирует НИКАК, однако client она ловит отлично... 100% проверено что оба коннектятся одинаково и не в них дело.. Что за нафиг творится в моем коде? Подскажите, кто знает... И еще, у меня встречалась точно такая же ошибка, когда я переносил код на другой линух. Причем слушал только один порт клиента. select наотрез отказывалась срабатывать на коннекты от клиента, однако перенеся этот же код на gentoo все вновь заработало.. В чем волшебство??? HELP!!!

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

 Оглавление

Сообщения по теме [Сортировка по времени, UBB]


1. "Проблема с сокетами и select"  
Сообщение от chip email(ok) on 20-Июн-06, 13:59 
>Функция vm_listenersock открывает неблокирующий сокет с указанным ей слушающим портом.

А каков глубокий смысл использования неблокирующего сокета совместно с select?

>Далее выкладываю код цикла обработки:

> select(mx+1, &readset, NULL, NULL, NULL);

Где проверка на ошибки + errno == EINTR

> if(FD_ISSET(listener_for_vmctrl, &readset))
> {
>     printf ("I recive connection from vmctrl...\n");
>     sock_vmctrl = accept(listener_for_client, NULL, NULL);
>     if (sock_vmctrl < 0)
>     {
>  perror("accept");
>  exit(3);
>     }
>
>     clients.insert(sock_vmctrl);
> }
>
> if(FD_ISSET(listener_for_client, &readset))
> {
>     printf ("I recive connection from client...\n");
>     sock_client = accept(listener_for_client, NULL, NULL);
>     if (sock_client < 0)
>     {
>  perror("accept");
>  exit(3);
>     }
>
>     clients.insert(sock_client);
> }
>    }
>
>И вот в чем сам фокус!! Если я в инструкции
>mx = max(listener_for_vmctrl, *max_element(clients.begin(), clients.end()));

насколько я могу судить по *max_element()... выбирает максимальный дескриптор из хранящихся в clients. А нужно выбирать максимальный из добавленных в readset, т.е. из
(listener_for_vmctrl и listener_for_client) + 1

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

2. "Проблема с сокетами и select"  
Сообщение от vic (??) on 20-Июн-06, 14:16 
и еще очибка:

> if(FD_ISSET(listener_for_vmctrl, &readset))
> {
>     printf ("I recive connection from vmctrl...\n");
>     sock_vmctrl = accept(listener_for_client, NULL, NULL);

здесь первый аргумент для accept() должен быть listener_for_vmctrl

...

> if(FD_ISSET(listener_for_client, &readset))
> {
>     printf ("I recive connection from client...\n");
>     sock_client = accept(listener_for_client, NULL, NULL);

...

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

3. "Проблема с сокетами и select"  
Сообщение от ufobject email(??) on 20-Июн-06, 20:44 
>и еще очибка:
>
>> if(FD_ISSET(listener_for_vmctrl, &readset))
>> {
>>     printf ("I recive connection from vmctrl...\n");
>>     sock_vmctrl = accept(listener_for_client, NULL, NULL);
>
>здесь первый аргумент для accept() должен быть listener_for_vmctrl
>
>...
>
>> if(FD_ISSET(listener_for_client, &readset))
>> {
>>     printf ("I recive connection from client...\n");
>>     sock_client = accept(listener_for_client, NULL, NULL);
>
>...

Ох!! С accept косяк действительно :)) Блин. Пол дня выглядывал, незаметил.
Я вот еще что не пойму, первый аргумент у select нафига нужен? Я man читал, но если честно нифига не понял... Поясните по человечески, если не сложно

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

4. "Проблема с сокетами и select"  
Сообщение от smb on 21-Июн-06, 02:12 
>>и еще очибка:
>>
>>> if(FD_ISSET(listener_for_vmctrl, &readset))
>>> {
>>>     printf ("I recive connection from vmctrl...\n");
>>>     sock_vmctrl = accept(listener_for_client, NULL, NULL);
>>
>>здесь первый аргумент для accept() должен быть listener_for_vmctrl
>>
>>...
>>
>>> if(FD_ISSET(listener_for_client, &readset))
>>> {
>>>     printf ("I recive connection from client...\n");
>>>     sock_client = accept(listener_for_client, NULL, NULL);
>>
>>...
>
>Ох!! С accept косяк действительно :)) Блин. Пол дня выглядывал, незаметил.
>Я вот еще что не пойму, первый аргумент у select нафига нужен?
>Я man читал, но если честно нифига не понял... Поясните по
>человечески, если не сложно

Совсем по-простому - мы передаем массив дескрипторов(второй параметр, fd_set *) - но кто знает количество дескрипторов в нем? ;)
"Аргумент maxfdp1 задает число проверяемых дескрипторов. Его значение на единицу больше максимального номера проверяемого дескриптора(поскольку его имя(индекс?) maxfdp1). Проверяются дескрипторы 0, 1, 2, ... , maxfdp - 1..." (с)

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

5. "Проблема с сокетами и select"  
Сообщение от ufobject email(??) on 21-Июн-06, 17:13 
>>>и еще очибка:
>>>
>>>> if(FD_ISSET(listener_for_vmctrl, &readset))
>>>> {
>>>>     printf ("I recive connection from vmctrl...\n");
>>>>     sock_vmctrl = accept(listener_for_client, NULL, NULL);
>>>
>>>здесь первый аргумент для accept() должен быть listener_for_vmctrl
>>>
>>>...
>>>
>>>> if(FD_ISSET(listener_for_client, &readset))
>>>> {
>>>>     printf ("I recive connection from client...\n");
>>>>     sock_client = accept(listener_for_client, NULL, NULL);
>>>
>>>...
>>
>>Ох!! С accept косяк действительно :)) Блин. Пол дня выглядывал, незаметил.
>>Я вот еще что не пойму, первый аргумент у select нафига нужен?
>>Я man читал, но если честно нифига не понял... Поясните по
>>человечески, если не сложно
>
>Совсем по-простому - мы передаем массив дескрипторов(второй параметр, fd_set *) - но
>кто знает количество дескрипторов в нем? ;)
>"Аргумент maxfdp1 задает число проверяемых дескрипторов. Его значение на единицу больше максимального
>номера проверяемого дескриптора(поскольку его имя(индекс?) maxfdp1). Проверяются дескрипторы 0, 1, 2,
>... , maxfdp - 1..." (с)

Т.е. просто нужно кол-во дискрипторов активных передать... Открытых в данный момент + 1.. Но почему в функции mx = max(listener_for_client, *max_element(clients.begin(), clients.end())); первым выступает listener_for_client? Ведь там может быть дискриптор произвольного значения, типа 10 или 12.. Это ведь не количество? Или я что то недопонимаю?

mx = max(listener_for_client, *max_element(clients.begin(), clients.end()));

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

6. "Проблема с сокетами и select"  
Сообщение от vic (??) on 21-Июн-06, 19:11 
>Т.е. просто нужно кол-во дискрипторов активных передать... Открытых в данный момент +
>1.. Но почему в функции mx = max(listener_for_client, *max_element(clients.begin(), clients.end())); первым
>выступает listener_for_client? Ведь там может быть дискриптор произвольного значения, типа 10
>или 12.. Это ведь не количество? Или я что то недопонимаю?
>
>
>mx = max(listener_for_client, *max_element(clients.begin(), clients.end()));

Читайте внимательней что вам пишут. В первом ответе chip уже написал про это.
Т.е. должно быть mx = max(listener_for_vmctrl, listener_for_client);

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

7. "Проблема с сокетами и select"  
Сообщение от kir (??) on 21-Июн-06, 19:46 
если bsd то лучше попробовать kevent
если линукс то там помоему ест poll

покрайней мере меньше заморочек

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

8. "Проблема с сокетами и select"  
Сообщение от ufobject email(??) on 21-Июн-06, 21:16 
>если bsd то лучше попробовать kevent
>если линукс то там помоему ест poll
>
>покрайней мере меньше заморочек


Благодарствую. Сори за невнимательность, но просто этот код был взят из примера, в правильности которого я как то даже не сомневался.

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

9. "Проблема с сокетами и select"  
Сообщение от smb on 23-Июн-06, 14:52 
>если bsd то лучше попробовать kevent
>если линукс то там помоему ест poll
>
>покрайней мере меньше заморочек

А еще лучше libevent и не изобретать велосипед ;)
Хотя понимать как это работает внутри - это очень даже хорошо......

Правка | Высказать мнение | Ответить | Cообщить модератору | Наверх

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру