Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> WSARecv 
:(
    Опции темы
zss
Дата 26.1.2007, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



создаю сокет
Код

SOCKET socket = WSASocket ( protocol, type, IPPROTO_TCP, NULL, 0, 0);

На этом сокете слушает сервер
Код

WORD index = WSAWaitForMultipleEvents (..., FALSE, 100, FALSE);
if ((index == WSA_WAIT_FAILED) || (index == WSA_WAIT_TIMEOUT))
{
    continue;
}
...
if (WSAEnumNetworkEvents (socket, event, ...) == SOCKET_ERROR)
{
   ...
}


На запросе сокет вываливает с ошибкой
Код

Операция на незаблокированном сокете не может быть завершена немедленно

Код ошибки 10035
Код

Resource temporarily unavailable. 
This error is returned from operations on nonblocking sockets that cannot be completed
immediately, for example recv when no data is queued to be read from the socket. It is a
nonfatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be
reported as the result from calling connect on a nonblocking SOCK_STREAM socket, since some time must
elapse for the connection to be established.


Серверу приходит блок данных. Но перед ним идет заголовок. Он всегда одной длинны. В заголовке
передается как правило длинна блока.

Тоесть сначала сервер вычитывает заголовок. После определеяет длинну данных и вычитывает данные.
Так вот если клиент отсылает все сразу, то тогда работает.
А если он отсылает тоже кусками (тоесть сначала заголовок, а потом и блок), то сервер заголовок получает, 
а для того, чтоб получить данные ему приходится ждать (простейший Sleep(100) помог).

Почему так ? 

З.Ы. И еще. событие FD_READ говорит о том, что серверу например пришел запрос. 
Тоесть поймав это событие можно обменивать данными.

Когда сервер пытается отослать данные, то приходит FD_WRITE. Для чего это событие вообще нужно
если через него можно определить лишь что сервер что-то пульнул в сокет 
PM MAIL ICQ   Вверх
Dude03
Дата 26.1.2007, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Насколько мне известно, то так заканчивается recv на асинхронном сокете, если нечего читать.
PM MAIL   Вверх
zss
Дата 28.1.2007, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Dude03, да  уменя так и есть - сокет неблокирующий. Но как реализовать ожидание новых событий FD_READ & FD_WRITE ?
PM MAIL ICQ   Вверх
Dude03
Дата 28.1.2007, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Асинхронная работа через объект события 
Если в программе нет процедуры обработки сообщений, то можно воспользоваться объектами событий. В этом случае алгоритм работы будет несколько иной: 

Создать объект события с помощью функции WSACreateEvent. 
Выбрать сокет с помощью функции WSAEventSelect. 
Ожидать событие с помощью функции WSAWaitForMultipleEvents. 
Давайте подробно рассмотрим все функции, необходимые для работы с объектами событий. 

Первым делом следует создать событие с помощью функции WSACreateEvent. Функции не надо передавать никаких параметров, она просто возвращает новое событие типа WSAEVENT: 

Код

WSAEVENT WSACreateEvent(void); 


Теперь нужно связать сокет с этим объектом и указать события, которые нам нужны. Для этого используется функция WSAEventSelect: 

Код

int WSAEventSelect (
    SOCKET s,
    WSAEVENT hEventObject,
    long lNetworkEvents
    )


Первый параметр — это сокет, события которого нас интересуют. Второй параметр — объект события. Последний параметр — это необходимые события. В качестве последнего параметра можно указывать те же константы, что рассматривались для функции WSAAsyncSelect (все они начинаются с префикса FD_). 

Раньше вы уже встречались с функциями WaitForSingleObject и WaitForMultipleObjects, которые ожидают наступления события типа HANDLE. Для сетевых событий используется похожая функция с именем WSAWaitForMultipleEvents:

Код

DWORD WSAWaitForMultipleEvents (
    DWORD cEvents,
    const WSAEVENT FAR *lphEvents,
    BOOL fWaitAll,
    DWORD dwTimeOUT,
    BOOL fAlertable
    );



Давайте рассмотрим каждый параметр: 

cEvents — количество объектов событий, изменение состояния которых нужно ожидать. Чтобы узнать максимальное число, воспользуйтесь константой WSA_MAXIMUM_WAIT_EVENTS; 
lphEvents — массив объектов событий, которые нужно ожидать; 
fWaitAll — режим ожидания событий. Если указано TRUE, то функция ожидает, пока все события не сработают, иначе — после первого передает управление программе; 
dwTimeOUT — временной интервал в миллисекундах, в течение которого нужно ожидать события. Если в этом временном интервале не возникло события, то функция возвращает значение WSA_WAIT_TIMEOUT. Если нужно ожидать бесконечно, то можно указать константу WSA_INFINITE; 
fAlertable — параметр используется при перекрестном вводе/выводе, который я не рассматриваю в этой книге, поэтому указан FALSE. 
Чтобы узнать, какое событие из массива событий сработало, нужно вычесть из возвращенного функцией WSAWaitForMultipleEvents значения константу WSA_WAIT_EVENT_0. 

Прежде чем вызывать функцию WSAWaitForMultipieEvents, все события в массиве должны быть пустыми. Если хотя бы одно из них будет занято, то функция сразу вернет управление программе, и не будет ожидания. После выполнения функции отработавшие события становятся занятыми, и после обработки их надо освободить. Для этого используется функция WSAResetEvent: 

Код

BOOL WSAResetEvent (
    WSAEVENT hEvent
    );


Функция очищает состояние события, указанного в качестве единственного параметра. 

Когда событие уже не нужно, его необходимо закрыть. Для этого используется функция WSACloseEvent. Функции следует передать объект события, который необходимо закрыть: 

Код

BOOL WSACloseEvent (
    WSAEVENT hEvent
    );


Если закрытие прошло успешно, то функция возвращает TRUE, иначе — FALSE. 

откуда-то=)
Может не 
Код

WORD index = WSAWaitForMultipleEvents (..., FALSE, 100, FALSE);

а
Код

WORD index = WSAWaitForMultipleEvents (..., FALSE, WSA_INFINITE, FALSE);


Добавлено @ 15:30 
Цитата(zss @  26.1.2007,  10:32 Найти цитируемый пост)
Когда сервер пытается отослать данные, то приходит FD_WRITE. Для чего это событие вообще нужно
если через него можно определить лишь что сервер что-то пульнул в сокет  

А если у тебя с сокетом работает 2 потока и надо узнать когда другой что-то запишет туда?

Это сообщение отредактировал(а) Dude03 - 28.1.2007, 15:27
PM MAIL   Вверх
zss
Дата 28.1.2007, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Dude03, спасибо за подробный ответ.

Но как все-таки ожидать. Может проще слушающий сокет сделать неблокирующим, а клиентскиу после WSAAccept блокирующим
и для него запускать отдельный поток. А после того как поток отработал - убивать сокет.

Но у меня почему-то после
Код

    SOCKET client = WSAAccept ( m_socket, (sockaddr*) &m_address,
                                &size, NULL, 0 );
    if (client == INVALID_SOCKET)
    {
        return false;
    }



клиент тоже оказывается неблокирующим. Почему ?
PM MAIL ICQ   Вверх
Dude03
Дата 28.1.2007, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Проще всего сделать через WSAAsyncSelect и сообщения Windows. Но там надо создать окно, которому и будет приходить сообщения.
PM MAIL   Вверх
zss
Дата 28.1.2007, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Dude03 @  28.1.2007,  23:07 Найти цитируемый пост)
Проще всего сделать через WSAAsyncSelect и сообщения Windows. Но там надо создать окно, которому и будет приходить сообщения.

не - окна не пойдут - у меня сервис smile


Цитата(Dude03 @  28.1.2007,  15:16 Найти цитируемый пост)
А если у тебя с сокетом работает 2 потока и надо узнать когда другой что-то запишет туда?

а как это вообще может быть. Я кручу цикл и ловлю события. Как потоку сказать что для него (для сокета которым он владеет) пришли еще данные ?

Добавлено @ 23:10 
Я ведь могу только определить для какого сокета пришло событие
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




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


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

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