Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> при closesocket FD_CLOSE не приходит, как лучше решить проблему 
V
    Опции темы
12usver12
Дата 9.1.2012, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 247
Регистрация: 5.1.2007

Репутация: нет
Всего: 1



есть стандартный код обработки событий сервером для асинхронных сокетов в очень упрощенной форме
Код

while(true)
    {
        Event =     WSAWaitForMultipleEvents(TotalEvents, (HANDLE*)&arrEvents, FALSE,WSA_INFINITE, FALSE);
                WSAEnumNetworkEvents(arrSocketInfo[Event - WSA_WAIT_EVENT_0]->Socket,arrEvents[Event - WSA_WAIT_EVENT_0], &NetworkEvents);    
                if (IsNetworkEvent(&NetworkEvents, FD_ACCEPT))
        {
            Accept = accept(arrSocketInfo[Event - WSA_WAIT_EVENT_0]->Socket, NULL, NULL); SOCKERRCHK(Accept);
            AddSocketInformation(Accept);
            tmpres = WSAEventSelect(Accept, arrEvents[TotalEvents - 1], FD_READ|FD_WRITE|FD_CLOSE);    SOCKERRCHK(tmpres); 
            printf("Socket %d got connected...\n", Accept);
        }
                if (IsNetworkEvent(&NetworkEvents, FD_READ)) 
        {
              OnRead(....);
                }

                 if (IsNetworkEvent(&NetworkEvents, FD_WRITE))
        {
                          .....
                }

                if (IsNetworkEvent(&NetworkEvents, FD_CLOSE))
        {
            printf("Closing socket information %d\n", arrSocketInfo[Event - WSA_WAIT_EVENT_0]->Socket);
            RemoveClientInformation(Event - WSA_WAIT_EVENT_0);
        }

вся схема отрабатывает как надо , но есть такие моменты в ходе программы когда нужно самому рвать соединение - т.е. иницицаторы разрыва мы а не клиент , и соответственно, мы не получаем события FD_CLOSE - на котором завязан весь контроль изменившегося числа клиентов (RemoveClientInformation(Event - WSA_WAIT_EVENT_0);  и апдейт числа евентов и массива евентов в WSAWaitForMultipleEvents(....)). С одной стороны самому при closesocket ничего не мешает сделать RemoveClientInformation... , но как пробудить тогда 
Код
WSAWaitForMultipleEvents(TotalEvents, (HANDLE*)&arrEvents, FALSE,WSA_INFINITE, FALSE);
  ? для того чтобы оно взяло мониторить новое кол-во хэндлов - что в этой ситуации можно сообразить то ?  есть ли возможность самому вручную "инициировать" network event FD_CLOSE для определенного хэндла - чтобы разбудить WSAWaitForMultipleEvents ?


Это сообщение отредактировал(а) 12usver12 - 9.1.2012, 10:20
PM MAIL   Вверх
feodorv
Дата 9.1.2012, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Microsoft често говорит:
Цитата

...FD_CLOSE network event is not posted after closesocket is called...


Цитата(12usver12 @  9.1.2012,  10:19 Найти цитируемый пост)
но как пробудить

Заводите специальное событие wakeEvent, вставляете его в массив arrEvents (увы, максимальное число клиентов при этом уменьшается на 1), затем проверяете, не оно ли сработало. Установка wakeEvent так же полезна при корректном завершеннии программы.

Самому делать SetEvent на одном из сокетных событий (например, на том, который ловит FD_ACCEPT) я несоветую, возможны очень неприятные ситуации, лучше пожертвовать одним клиентом (их и так 63 штуки остаётся ;))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
12usver12
Дата 9.1.2012, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 247
Регистрация: 5.1.2007

Репутация: нет
Всего: 1



Цитата(feodorv)

Самому делать SetEvent на одном из сокетных событий (например, на том, который ловит FD_ACCEPT) я несоветую

вначале так и делал через WSASetEvent, угу так и есть FD_ACCEPT потом не приходит 

Цитата(feodorv)

лучше пожертвовать одним клиентом (их и так 63 штуки остаётся ;))

это мелочи действительно 
Цитата(feodorv)

Заводите специальное событие wakeEvent, вставляете его в массив arrEvents

я так понимаю что для одной группы из 64 клиентов , этого wakeclient лучше добавлять в самое начало массива хэндлов. 
на этом wakeEvent что лучше делать SetEvent или WSASetEvent или без разницы т.е создавать через WSACreateEvent или CreateEvent ?

Это сообщение отредактировал(а) 12usver12 - 9.1.2012, 13:53
PM MAIL   Вверх
feodorv
Дата 9.1.2012, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(12usver12 @  9.1.2012,  13:28 Найти цитируемый пост)
этого wakeclient лучше добавлять в самое начало массива хэндлов

Это без разницы (хотя, может, и есть малюсенькая разница, пока не могу сказать), главное - корректно обработать. Если вставлять в начало, потом единицу из индекса вычитать надо ;)

Кстати, закрывать сокет можно и в другом потоке, а вот высвобождать соответствующее ему событие - только в ожидающем WSAWaitForMultipleEvents потоке. Честно, не помню, почему после closesocket не стоит устанавливать отвечающее ему событие (чтобы пробудить wait-функцию, там тоже какой-то неприятный эффект был). Лучше пользовать добавочное событие с дальнейшим перебором клиентов (жив - не жив))))

То есть:
  •  в одном потоке - closesocket( arrSocketInfo[index]->Socket ); arrSocketInfo[index]->Socket = INVALID_SOCKET; SetEvent( wakeEvent );
  •  в другом потоке - WSAWait...(...); if( Event == 0 ) for( index... ) if( arrSocketInfo[index]->Socket == INVALID_SOCKET ){ CloseHandle( arrSocketInfo[index]->Event ); RemoveClient( index ); }

Цитата(12usver12 @  9.1.2012,  13:28 Найти цитируемый пост)
на этом wakeEvent что лучше делать SetEvent или WSASetEvent или без разницы

Вот это однозначно без разницы. Можно и Wait... вместо WSAWait...)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
12usver12
Дата 11.1.2012, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 247
Регистрация: 5.1.2007

Репутация: нет
Всего: 1



Цитата

Это без разницы (хотя, может, и есть малюсенькая разница, пока не могу сказать), главное - корректно обработать. Если вставлять в начало, потом единицу из индекса вычитать надо ;)

вообще не нужно вычитать , если ты его добавляешь как отдельного клиента , по крайней мере у меня - хотя м.б. зависит от реализации

Цитата

Кстати, закрывать сокет можно и в другом потоке, а вот высвобождать соответствующее ему событие - только в ожидающем WSAWaitForMultipleEvents потоке.
Честно, не помню, почему после closesocket не стоит устанавливать отвечающее ему событие

ну я собсно connect,accept и close обрабатываю в одном потоке , а отправку и принятие данных в других, перед каким-то телодвижением например закрытие сокета пробуждаю wait , а то вроде глюки были когда сначала закрывал сокет.
Цитата

на этом wakeEvent что лучше делать SetEvent или WSASetEvent или без разницы т.е создавать через WSACreateEvent или CreateEvent

как показала практика - без разницы
ну и конечно там где уже несколько потоков пошло - не забывать про синхронизацию 

p.s. спс за wakeclient , а то чувствуется делал бы через ж*  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0633 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.