Here's my program:
I use the semaphore to get messages from another thread.
-----
this->_hEvent = WSACreateEvent();
while (1)
{
HANDLE TabEvents[2];
TabEvents[0] = this->_th->_inSem->_hSemaphore;
TabEvents[1] = this->_hEvent;
DWORD WaitRes = WaitForMultipleObjects(2, TabEvents, FALSE, INFINITE);
if (WaitRes == WAIT_FAILED)
throw new NetworkException("WaitForMultipleObjects",
WSAGetLastError());
switch(WaitRes)
{
case WSA_WAIT_EVENT_0:
[...]
//NEW CLIENT ! (already accepted)
int iMode = 1;
if (ioctlsocket(client->getSocket(), FIONBIO, (u_long FAR*) &iMode)
==
SOCKET_ERROR)
[...] // error: close ....
int nRet = WSAEventSelect(cursocket, this->_hEvent,
FD_READ|FD_CLOSE|FD_WRITE);
if (nRet == SOCKET_ERROR)
[...] // error: close ...
break;
case WSA_WAIT_EVENT_0 + 1:
WSANETWORKEVENTS events;
for ([...]) //browse clients
{
int nRet = WSAEnumNetworkEvents(client->getSocket(), this->_hEvent,
&events);
int action = events.lNetworkEvents;
if (nRet == SOCKET_ERROR)
action = FD_CLOSE;
if (FD_READ & action)
{
if (this->receiveFromClient(client) != SOCKET_ERROR)
{
[...]
}
else
action = FD_CLOSE;
}
if (FD_WRITE & action)
{
[...]
}
if (FD_CLOSE & action)
{
this->closeClient(client);
}
}
break;
}
}
----
void closeClient([...])
{
int nRet = WSAEventSelect(client->getSocket(), this->_hEvent, 0);
if (nRet == SOCKET_ERROR)
throw new NetworkException("WSAEventSelect", WSAGetLastError());
closesocket ...
}
----
With this code I have sometimes an infinite loop: I already have unset
sockets on "this->_hEvent" but the WaitForMultipleObjects quits with
WSA_WAIT_EVENT_0 + 1 (this->_hEvent)...
Please Help, I don't know if I use well the WSAEventSelect function....
Thanks in advance.
You will have to be more specific. You've *coded* an infinite loop, so
without more details, there's no reason to believe the code isn't doing
exactly what you told it to do.
What is it that you think the code should do, what is it doing instead, and
under what circumstance does it do the wrong thing rather than the right
thing?
I skimmed through the code as best I could, and I don't see anything
obviously wrong. I may have missed something; you posted it without any
indentation whatsoever, making it VERY hard to read. I don't spend much
time trying to decipher hard-to-read code.
You do have a couple of superfluous elements. You don't need to set the
socket to non-blocking. WSAEventSelect() does this for you. And you don't
need to reset the WSAEventSelect() state for the socket before closing it.
That's just a waste of time.
Pete
> I may have missed something; you posted it without any
> indentation whatsoever, making it VERY hard to read.
I have posted the code with google groups and I have posted with
indentation:
http://groups.google.fr/group/alt.winsock.programming/browse_thread/thread/dcc62313db39cf07/e67fb86303750095#e67fb86303750095
> You do have a couple of superfluous elements. You don't need to set the
> socket to non-blocking.
Ok thanks for the information.
> And you don't need to reset the WSAEventSelect()
> state for the socket before closing it.
If I don't use it WaitForMultipleObjects quits evrey time on
WSA_WAIT_EVENT_0 + 1
I have some threads: It's a "kernel" implentation with some modules.
One module accept the connection, another read/write/close, another
treat the readed data ...
Modules have a semaphore to know when a message arrived from another
thread.
My problem is with the read/write/close module: I have a while(1) with
a WaitForMultipleObjects on the semaphore and on sockets.
I am sure that my socket is closed but sometimes
WaitForMultipleObjects...
Thanks again for your help
Don't post with Google Groups. It screws up your post, and people using
normal newsreaders don't see what you think they see.
You may think you included indendation, but I assure you that on this end,
there is none.
> [...]
>> And you don't need to reset the WSAEventSelect()
>> state for the socket before closing it.
>
> If I don't use it WaitForMultipleObjects quits evrey time on
> WSA_WAIT_EVENT_0 + 1
Well, that's a problem then. I suggest that, rather than doing the wrong
thing to fix a wrong thing, you figure out why the original wrong thing is
happening.
Personally, my bet is that you didn't reset the network event handle.
WSACreateEvent() gives you an event handle that does NOT auto-reset. Once
you've handled the event, you need to reset it yourself.
Calling WSAEventSelect() is not the right way to reset the event.
> I have some threads: It's a "kernel" implentation with some modules.
> One module accept the connection, another read/write/close, another
> treat the readed data ...
>
> Modules have a semaphore to know when a message arrived from another
> thread.
Fine. That was apparent from the original code, but still...fine.
> My problem is with the read/write/close module: I have a while(1) with
> a WaitForMultipleObjects on the semaphore and on sockets.
An infinite loop. Which you coded.
> I am sure that my socket is closed but sometimes
> WaitForMultipleObjects...
That's not a complete sentence.
> Thanks again for your help
I'm still not clear on what isn't working. I doubt anyone else is too. So
far, your only complaint is that there's an infinite loop, but as you've
explained twice already, the infinite loop is one you wrote yourself. It's
hardly a surprise there's an infinite loop.
Pete
I'm sorry but i'm not english and I have a very poor level in emglish
so sorry again.
My problem is not the infinite loop but the fact that
WaitForMultipleObjects does not wait sometimes...
If WaitForMultipleObjects returns, it does so for a reason. Until you
describe the condition in which it returns, but you don't expect it to, it's
impossible for anyone to suggest why it is returning when you don't expect
it to.
I will agree with Casper that it might be better to use the Winsock "WSAxxx"
version of the function, and/or to do more complete handling of possible
return values. But doing so may or may not resolve your problem. No one
here can say until you tell us why WaitForMultipleObjects is returning, and
why it is you think it shouldn't be returning.
Pete
My problem is that WaitForMultipleObjects returns whereas I have no
more socket connected (I'm sure about that), I am sure that the return
is not due to the semaphore ...
Why is that a problem? Would you prefer that it NOT return when you have no
more sockets connected?
I still don't understand what behavior it is you expect to see. You passed
in an event handled corresponding to a socket. If the socket is
disconnected, that's a network event you would be alerted to. In that case,
WaitForMultipleObjects should return. If you don't want it to, then you
need to not set the flags that would cause that to happen (FD_READ and
FD_CLOSE).
The bottom line here:
WaitForMultipleObjects returns only under very specific conditions.
According to you, the condition is that the second event handle parameter
you pass to it is set. If you don't want WaitForMultipleObjects to return
in that situation, you need to ensure that it doesn't get set in that
situation.
Pete
All sockets are closed, I have unset every socket in the handler. I
don't understand why the WaitForMultipleObjects return whereas I have
no socket set in the handler.
> All sockets are closed, I have unset every socket in the handler. I
> don't understand why the WaitForMultipleObjects return whereas I have
> no socket set in the handler.
It returns because it has nothing to wait for.
DS
Oh, no no no.
You should never reset the event yourself. The network stack should keep the
correspondence between events occurred and events signalled. Your job, as a
Winsock user, is to allow it to do so.
You accomplish this by calling the WSAEnumNetworkEvents function, so as to be
informed of the socket events that are associated with the WSAEVENT object
that was signalled. The socket stack will use that call to
WSAEnumNetworkEvents to reset the event, or to signal it if there are more
network events that occurred in between.
Resetting the event yourself will lead to race conditions that are hard to
debug, but result in occasional unreliability under stress.
>Calling WSAEventSelect() is not the right way to reset the event.
WSAEventSelect is about associating and disassociating a socket with an event,
and a possible mask of events. Note that for some events, calling
WSAEventSelect again will re-trigger an event notification that you have
already received.
Alun.
~~~~
[Please don't email posters, if a Usenet response is appropriate.]
--
Texas Imperial Software | Find us at http://www.wftpd.com or email
23921 57th Ave SE | al...@wftpd.com.
Washington WA 98072-8661 | WFTPD, WFTPD Pro are Windows FTP servers.
Fax/Voice +1(425)807-1787 | Try our NEW client software, WFTPD Explorer.
My bad. I knew the event is created as a manual reset. I forgot that it's
Winsock that handles the event handle state, not the application.
Thanks! :)
Pete
And how can I flush an event ,after disassociating a socket. To be sure
that I will not receive another notification from the closed socket.
WSAEnumNetworkEvents will flush events as it tells you what they are;
closesocket will permanently disassociate the event and the socket handle;
WSAEventSelect may be used if you don't want to monitor events on a socket any
more, but want to keep the socket open. [Say, for instance, you're going to
hand it off to another piece of code that doesn't use events]
If that last is the case, you would do well to read the documentation:
"The WSAEventSelect function automatically sets socket s to nonblocking mode,
regardless of the value of lNetworkEvents. To set socket s back to blocking
mode, it is first necessary to clear the event record associated with socket s
via a call to WSAEventSelect with lNetworkEvents set to zero, in which case
the hEventObject parameter will be ignored. You can then call ioctlsocket or
WSAIoctl to set the socket back to blocking mode."