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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> WSAWaitForMultipleEvents и FD_WRITE событие, только раз приходит 
:(
    Опции темы
12usver12
Дата 23.12.2011, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Тренируюсь с реализацией слушающего сервера на winsock events , все хорошо получается но не могу уловить одного момента
вот код сервера,  убрал fail проверки, чтобы не загромождать код  
Код

    while(true)
    {
        // после accept и после первого события - т.е. FD_ACCEPT и FD_WRITE|FD_READ - уходит в вечное ожидание событий , пока
                // клиент не отправит мессидж или приконнекитться/разорвет соединение
        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)) 
        {
             .....
                }
                // после коннекта первого клиента и его accepta, сюда доходит только один раз событие дальше виснет на WSAWaitForMultipleEvents
                 if (IsNetworkEvent(&NetworkEvents, FD_WRITE))
        {
                          .....
                }
                if (IsNetworkEvent(&NetworkEvents, FD_CLOSE))
        {
            printf("Closing socket information %d\n", arrSocketInfo[Event - WSA_WAIT_EVENT_0]->Socket);
            RemoveSocketInformation(Event - WSA_WAIT_EVENT_0);
        }


клиент 

Код

if (connectSocket(sConnect, "127.0.0.1",7887))
    {
        while(true)
        {
            ZeroMemory(recvdata,1024);
                        // char* testdata = "test";
            //sendSocket(sConnect, testdata, lstrlenA(testdata));
            //Sleep(10000);
            printf("\r\nrecvSocket..."); 
            if (recv(sConnect, recvdata, 1024,0))
                printf("\r\nreceived: %s",recvdata); 
        }



вцелом модель работает замечательно , WSAWaitForMultipleEvents без проблем реагирует на соединения новых клиентов и отправки с их стороны данных, но при коннекте нового клиента событие FD_WRITE (возможность отправки данных) предоставляется только один раз при accepte нового сокета клиента
Цитата(msdn)

The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with a call to the connect, ConnectEx, WSAConnect, WSAConnectByList, or WSAConnectByName function or when a socket is accepted with accept, AcceptEx, or WSAAccept function and then after a send fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the application will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is set.

таким образом отправить клиенту данные я могу только если он первый отправит данные (при этом я получу событие FD_READ|FD_WRITE)
или приконнектиться, в других случаях FD_WRITE так и не приходит
А как мне быть если я хочу отправить несколько сообщений клиенту (WSASend) не дожидаясь пока он что-то пошлет ? 
пробовал ставить WSAWaitForMultipleEvents с таймаутом и дальше просто делать WSASend/send не получив соответственно событие FD_WRITE и получаю ошибку WSAEWOULDBLOCK
PM MAIL   Вверх
feodorv
Дата 23.12.2011, 21:58 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(12usver12 @  23.12.2011,  20:06 Найти цитируемый пост)
таким образом отправить клиенту данные я могу только если он первый отправит данные

Откуда такое заключение?

FD_WRITE происходит в двух случаях:
  • сразу после connect/accept 
  • после неудачной попытки записи в сокет, закончившейся WSAEWOULDBLOCK (то есть когда вы успеваете писать в сокет больше, чем успевает передаться по сети)
и эти случаи никак не связаны с посылкой данных серверу от клиента.

Я лично не надеюсь на приход FD_WRITE сразу после connect/accept и спокойно пишу в сокет (сокет и так готов для записи).
И другое дело второй случай. Тогда жду FD_WRITE и переповторяю попытку записи. 

Иными словами, если при записи не было WSAEWOULDBLOCK, то писать в (присоединённый) сокет можно сколько угодно. Более того, ждать прихода FD_WRITE, чтобы осуществить запись в сокет, бесполезно. Система не будет вас беспрерывно снабжать сообщениями FD_WRITE, когда сокет и так доступен для записи.
Если приключился WSAEWOULDBLOCK, то необходимо ждать FD_WRITE.

Это сообщение отредактировал(а) feodorv - 23.12.2011, 22:20


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


Бывалый
*


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

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



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


 




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


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

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