В приведенном ниже коде событие hConnectedEvt никогда
не устанавливается и WSAWaitForMultipleEvents(...) всегда
завершается по тайм — ауту, хотя само соединение
устанавливается.
Известно, что при соединении так — же срабатывает FD_WRITE.
Если использовать его вместо FD_CONNECT, то все работает
нормально. Не могу понять, почему не работает FD_CONNECT.
Если кто — то сталкивался с такой проблемой и знает в чем дело,
просьба подсказать.
Здравствуйте, butcher, Вы писали:
B>Здравствуйте, stream15, Вы писали:
S>>В приведенном ниже коде событие hConnectedEvt никогда S>>не устанавливается и WSAWaitForMultipleEvents(...) всегда
B>Приведите полный код, возможно тогда станет ясно..
Ниже я привожу полный код, но ситуация поменялась
на противоположную, которая ничуть не лучше.
Вышеописанный вариант мне воспроизвести не удалось.
У меня установлен firewall, может он как — то
вмешивался, хотя я его отключал, может не всегда...
Установлен так же локальный IIS, но я его
на всякий случай остановил.
1. Компьютер не подключен ни к сети ни к Inet.
Я указываю локальный IP адрес и порт, который
никто не прослушивает. При этом
DWORD dwRes = WSAWaitForMultipleEvents(1, &hConnectedEvt, FALSE, 5000, FALSE);
пролетает, как будто hConnectedEvt взведен до входа в ожидание.
Если я запускаю локальный сервер, слушающий порт 1111, то
устанавливается соединение и WSAWaitForMultipleEvents(...)
уже "пролетает" на законных основаниях.
Вместо локального я могу указать любой адрес, ситуация не меняется.
2. Компьютер подключен к Inet. В этом случае если указан не
локальный произвольный адрес, WSAWaitForMultipleEvents(...)
завершается по тайм — ауту, как и положено.
3. Опять же, если вместо FD_CONNECT использовать FD_WRITE,
все работает как надо.
Юрий
// ScaleCons.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <conio.h>
#include <crtdbg.h>
Здравствуйте, stream15, Вы писали:
S>Здравствуйте, butcher, Вы писали:
B>>Здравствуйте, stream15, Вы писали:
S>>>В приведенном ниже коде событие hConnectedEvt никогда S>>>не устанавливается и WSAWaitForMultipleEvents(...) всегда
B>>Приведите полный код, возможно тогда станет ясно..
S>Ниже я привожу полный код, но ситуация поменялась S>на противоположную, которая ничуть не лучше. S>Вышеописанный вариант мне воспроизвести не удалось. S>У меня установлен firewall, может он как — то S>вмешивался, хотя я его отключал, может не всегда... S>Установлен так же локальный IIS, но я его S>на всякий случай остановил.
S>1. Компьютер не подключен ни к сети ни к Inet. S> Я указываю локальный IP адрес и порт, который S> никто не прослушивает. При этом S> DWORD dwRes = WSAWaitForMultipleEvents(1, &hConnectedEvt, FALSE, 5000, FALSE); S> пролетает, как будто hConnectedEvt взведен до входа в ожидание. S> Если я запускаю локальный сервер, слушающий порт 1111, то S> устанавливается соединение и WSAWaitForMultipleEvents(...) S> уже "пролетает" на законных основаниях. S> Вместо локального я могу указать любой адрес, ситуация не меняется.
S>2. Компьютер подключен к Inet. В этом случае если указан не S> локальный произвольный адрес, WSAWaitForMultipleEvents(...) S> завершается по тайм — ауту, как и положено.
S>3. Опять же, если вместо FD_CONNECT использовать FD_WRITE, S> все работает как надо.
У Вас работает все правильно. Если сервер на порту 1111 не запущен, вы вызываете connect на локальной машине очень быстро вернут ошибку о недоступности данного сервиса. При этом событие FD_CONNECT установят. С помощью WSAEnumNetworkEvents можно было бы узнать о том, что событие взведено и код ошибки ( WSAECONNREFUSED веротяно ).
В Вашем коде присутствуют логические ошибки:
connect проверяется на ошибку, но не проверяется на причину ошибки. Ожидать установки события следует лишь в случае кода WSAEWOULDBLOCK.
после установки события следует проверять причину его установки ( см. WSAEnumNetworkEvents ).
И уберите Вы эти WSASetLastError(0)
Да пребудет с тобою сила
Re[4]: Не срабатывает событие FD_CONNECT
От:
Аноним
Дата:
14.12.05 12:28
Оценка:
Здравствуйте, TarasCo,
Благодарю, теперь мне все понятно...
TC>И уберите Вы эти WSASetLastError(0)
Обязательно уберу. Просто в моем первоначальном
тестовом коде я не реагировал на ошибки а
лишь сообщал о них и первая же WSAError
присутствовала в последующих сообщениях
при вызове WSAGetLastError(),
хотя дальше реальных ошибок не было.
Ну а потом решил оставить....
Здравствуйте, Аноним, Вы писали:
TC>>И уберите Вы эти WSASetLastError(0)
А>Обязательно уберу. Просто в моем первоначальном А>тестовом коде я не реагировал на ошибки а А>лишь сообщал о них и первая же WSAError А>присутствовала в последующих сообщениях А>при вызове WSAGetLastError(), А>хотя дальше реальных ошибок не было.
Позвольте в этом усомнится... IMHO после каждого системного вызова WSAGetLastError ( GetLastError) будет возвращать статус этого самого вызова — т.е сообщение об ошибке не сохраняется.
Здравствуйте, TarasCo, Вы писали:
TC>Здравствуйте, Аноним, Вы писали:
TC>>>И уберите Вы эти WSASetLastError(0)
А>>Обязательно уберу. Просто в моем первоначальном А>>тестовом коде я не реагировал на ошибки а А>>лишь сообщал о них и первая же WSAError А>>присутствовала в последующих сообщениях А>>при вызове WSAGetLastError(), А>>хотя дальше реальных ошибок не было.
TC>Позвольте в этом усомнится... IMHO после каждого системного вызова WSAGetLastError ( GetLastError) будет возвращать статус этого самого вызова — т.е сообщение об ошибке не сохраняется.
MSDN: A successful function call, or a call to WSAGetLastError, does not reset the error code. To reset the error code, use the WSASetLastError function call with iError set to zero. A getsockopt SO_ERROR also resets the error code to zero.
Понимаете в чем дело, если Вы сделали первый системный вызов который завершился ошибкой и затем
WSAGetLastError(), она вернет Вам ошибку последнего НЕУДАЧНОГО системного вызова. Далее вы делаете любое количество системных вызовов которые завершаются удачно и Вас "спасает" только то, что в данном случае Вам нет необходимости вызывать WSAGetLastError(). Но если Вы это сделаете, вы получите ошибку первого системного вызова.
Которая будет хранится пока существует данная thread или Вы ее не сбросите или она не затрется новой ошибкой.
Я наблюдал это сам. WSASetLastError() or SetLastError() существуют не зря. Предположим есть функция
которая не возвращает значение "успех\неудача", а только устанавливает LastError. Нет другого способа
корректного ее использования как:
SetLastError(0);
StrangeFunction();
int nRes = GetLastError();
Иначе при успешном завершении функции StrangeFunction() Вы рискуете получить последнюю
ошибку в данной thread, если она была.
Юрий
Re[7]: Не срабатывает событие FD_CONNECT
От:
Аноним
Дата:
15.12.05 02:00
Оценка:
Здравствуйте, stream15, Вы писали:
S>Здравствуйте, TarasCo, Вы писали:
TC>>Здравствуйте, Аноним, Вы писали:
TC>>>>И уберите Вы эти WSASetLastError(0)
А>>>Обязательно уберу. Просто в моем первоначальном А>>>тестовом коде я не реагировал на ошибки а А>>>лишь сообщал о них и первая же WSAError А>>>присутствовала в последующих сообщениях А>>>при вызове WSAGetLastError(), А>>>хотя дальше реальных ошибок не было.
TC>>Позвольте в этом усомнится... IMHO после каждого системного вызова WSAGetLastError ( GetLastError) будет возвращать статус этого самого вызова — т.е сообщение об ошибке не сохраняется.
S>MSDN: A successful function call, or a call to WSAGetLastError, does not reset the error code. To reset the error code, use the WSASetLastError function call with iError set to zero. A getsockopt SO_ERROR also resets the error code to zero.
S>Понимаете в чем дело, если Вы сделали первый системный вызов который завершился ошибкой и затем S>WSAGetLastError(), она вернет Вам ошибку последнего НЕУДАЧНОГО системного вызова. Далее вы делаете любое количество системных вызовов которые завершаются удачно и Вас "спасает" только то, что в данном случае Вам нет необходимости вызывать WSAGetLastError(). Но если Вы это сделаете, вы получите ошибку первого системного вызова. S>Которая будет хранится пока существует данная thread или Вы ее не сбросите или она не затрется новой ошибкой. S>Я наблюдал это сам. WSASetLastError() or SetLastError() существуют не зря. Предположим есть функция S>которая не возвращает значение "успех\неудача", а только устанавливает LastError. Нет другого способа S>корректного ее использования как: S>SetLastError(0); S>StrangeFunction(); S>int nRes = GetLastError();
S>Иначе при успешном завершении функции StrangeFunction() Вы рискуете получить последнюю S>ошибку в данной thread, если она была.
S>Юрий
гм. оффтопик, однако если эта самая StrangeFunction() сигнализирует через код ошибки,
то она сама должна вызвать SetLastError(0) в случае успеха, так что функция-то нужна,
а вот сброс перед вызовом таких функций не нужен (или тода такая функция семантически неверна)
Здравствуйте, Аноним, Вы писали:
S>>Понимаете в чем дело, если Вы сделали первый системный вызов который завершился ошибкой и затем S>>WSAGetLastError(), она вернет Вам ошибку последнего НЕУДАЧНОГО системного вызова. Далее вы делаете любое количество системных вызовов которые завершаются удачно и Вас "спасает" только то, что в данном случае Вам нет необходимости вызывать WSAGetLastError(). Но если Вы это сделаете, вы получите ошибку первого системного вызова. S>>Которая будет хранится пока существует данная thread или Вы ее не сбросите или она не затрется новой ошибкой. S>>Я наблюдал это сам. WSASetLastError() or SetLastError() существуют не зря. Предположим есть функция S>>которая не возвращает значение "успех\неудача", а только устанавливает LastError. Нет другого способа S>>корректного ее использования как: S>>SetLastError(0); S>>StrangeFunction(); S>>int nRes = GetLastError();
S>>Иначе при успешном завершении функции StrangeFunction() Вы рискуете получить последнюю S>>ошибку в данной thread, если она была.
S>>Юрий
А>гм. оффтопик, однако если эта самая StrangeFunction() сигнализирует через код ошибки, А>то она сама должна вызвать SetLastError(0) в случае успеха, так что функция-то нужна, А>а вот сброс перед вызовом таких функций не нужен (или тода такая функция семантически неверна)
Насчет семантически верна/неверна это скорее субъективная оценка. Конечно с такой функцией
работать менее приятно, но они есть и в Windows API. Главное чтобы это было отражено в
документации. К тому же могут быть особые причины для написания таких функций.
MSDN:
If the previous value of the specified 32-bit integer is zero, and the function succeeds,
the return value is zero, but the function does not clear the last error information.
This makes it difficult to determine success or failure. To deal with this, you should
clear the last error information by calling SetLastError(0) before calling SetWindowLong.
Then, function failure is indicated by a return value of zero and a GetLastError result
that is nonzero.