?
Solved

Using WSAEventSelect and WSAWaitForMultipleEvents

Posted on 2004-10-30
16
Medium Priority
?
2,851 Views
Last Modified: 2013-12-03
I am a server. I need to accept many connections. I want to accept a connection, start servicing it and loop back up and repeat.

I have used the following logic but it does not seem to work as intended.

WSAStartup(0x202, &wsaData);
listenSocket = WSASocket(AF_INET, DEFAULT_PROTO, 0, NULL, 0, dwFlags);
bind(listenSocket, (struct sockaddr*)&local, sizeof(local);
listen(listenSocket, SOMAXCONN);
eventObject  = WSACreateEvent();
WSAEventSelect( listenSocket, eventObject, FD_ACCEPT );
for (;;)
{
    WSAWaitForMultipleEvents( 1, &eventObject, FALSE, WSA_INFINITE, FALSE );
    socket = WSAAccept(listenSocket, (struct sockaddr *)&from, &fromlen, conditionFunc, 0); // conditionFunc returns CF_ACCEPT
    .... process socket here ....
}
0
Comment
Question by:ESQuicksall
  • 12
  • 2
15 Comments
 

Author Comment

by:ESQuicksall
ID: 12454204
I failed to say what happens ---

The WSAWaitForMultipleEvents sometimes does not seem to wait. When I call WSAAccept, the socket is -1 and WSAGetNextError is 10035 (A non-blocking socket operation could not be completed immediately). If I put a breakpoint on WSAWaitForMultipleEvents, the WSAAccept usually (but not always) returns a good socket.
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 2000 total points
ID: 12455897
WSANETWORKEVENTS events;
WSAStartup(0x202, &wsaData);
listenSocket = WSASocket(AF_INET, DEFAULT_PROTO, 0, NULL, 0, dwFlags);
bind(listenSocket, (struct sockaddr*)&local, sizeof(local);
eventObject  = WSACreateEvent();
WSAEventSelect( listenSocket, eventObject, FD_ACCEPT );
for (;;)
{
    if ( WSAWaitForMultipleEvents( 1, &eventObject, FALSE, WSA_INFINITE, FALSE ) == WAIT_OBJECT_0 )
    {
         DWORD dwResult = WSAEnumNetworkEvents(listenSocket , eventObject, &events);

         if ( events.lNetworkEvents & FD_ACCEPT )
         {
               socket = WSAAccept(listenSocket, (struct sockaddr *)&from, &fromlen, conditionFunc, 0);
               ...
         }
    }
    else
    {
        // error handling, break
    }
}



0
 

Author Comment

by:ESQuicksall
ID: 12457889
First, I assume you also want me to add the listen between the bind and the WSACreateEvent. I tried it without that and seems to be needed.

So I tried what you said but now WSAAccept returns 10014 "The system detected an invalid pointer address in attempting to use a pointer argument in a call".

Note that dwResult is a 0, listenSocket is a 0x7a0, eventObject is 0x784 and events.lNetworkEvents is 8.

from and fromLen are as follows:
    int                         fromlen;
    struct sockaddr_in  from;

I have seen this error in the past when all pointers are correct. I think there is an error but I think WSASockets reports it incorrectly. I just don't know where the error is.

At least you have agreed that I understand the usage of the functions (yours and mine are very similar).

Eddy
0
Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

 

Author Comment

by:ESQuicksall
ID: 12458143
Your code and mine are basically the same because I have only one object. Since yours gave the strange 10014, I went back to mine which was giving the 10035.

I added WSAResetEvent( &eventObject ) to my code after the WSAAccept and got by the 10035 that it was producing. But now when I do the WSARecv (which is basically where I had the ...'s) I never get the callback which should happen due to the data that is received. I used Ethereal to verify that I am getting the data.

So the code is now like this:

WSAStartup(0x202, &wsaData);
listenSocket = WSASocket(AF_INET, DEFAULT_PROTO, 0, NULL, 0, dwFlags);
bind(listenSocket, (struct sockaddr*)&local, sizeof(local);
listen(listenSocket, SOMAXCONN);
eventObject  = WSACreateEvent();
WSAEventSelect( listenSocket, eventObject, FD_ACCEPT );
for (;;)
{
    WSAWaitForMultipleEvents( 1, &eventObject, FALSE, WSA_INFINITE, FALSE );
    socket = WSAAccept(listenSocket, (struct sockaddr *)&from, &fromlen, conditionFunc, 0); // conditionFunc returns CF_ACCEPT
    WSAResetEvent( &eventObject );
    WSARecv(,,,,,, TOEHW_RecvComplete);
   // a call to TOEHW_RecvComplete should occur after calling WSAWaitForMultipleEvents when it blocks
}

Note that the basic code has been working for a very long time. This is the old code:

WSAStartup(0x202, &wsaData);
listenSocket = WSASocket(AF_INET, DEFAULT_PROTO, 0, NULL, 0, dwFlags);
bind(listenSocket, (struct sockaddr*)&local, sizeof(local);
listen(listenSocket, SOMAXCONN);
for (;;)
{
    socket = WSAAccept(listenSocket, (struct sockaddr *)&from, &fromlen, conditionFunc, 0); // conditionFunc returns CF_ACCEPT
    WSARecv(,,,,,, TOEHW_RecvComplete);
   // a call to TOEHW_RecvComplete occurs after calling WSAAccept when it blocks
}




0
 

Author Comment

by:ESQuicksall
ID: 12472148
AlexFM, do you have any other ideas as to what is going on?

Eddy
0
 

Author Comment

by:ESQuicksall
ID: 12523705
Does anyone have any ideas as to what may be going on?
0
 

Author Comment

by:ESQuicksall
ID: 12545431
Does anyone know how I can raise the points on this? I really need an answer.
0
 

Author Comment

by:ESQuicksall
ID: 12818938
No correct answer has been given and my response has not been answered. I will be asking for a refund if there are no objections.

AlexFM, if I have misunderstood your comment, please let me know.

Eddy
0
 

Author Comment

by:ESQuicksall
ID: 12863085
DanRollins,

Can you please see if you know the answer to this or if you know someone that does?

Eddy
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 12864901
Sorry, I do not know the answer.  You might get more response by asking in the C++ section.

Did you look at all previous answers containing "WSAWaitForMultipleEvents"?

   http://search.experts-exchange.com/search.jsp?query=WSAWaitForMultipleEvents

-- Dan
0
 

Author Comment

by:ESQuicksall
ID: 12878790

I may have found the problem with my original code. I forgot to set fromlen before I called WSAAccept:

    fromlen = sizeof(from)

I'll let you know if this works.

Eddy
0
 

Author Comment

by:ESQuicksall
ID: 12880131
It turns out that that bug correction did not help. So, I'm still stuck.
0
 

Author Comment

by:ESQuicksall
ID: 12896148
I got it working. I had three errors ...

(1) I had not set fromlen before the WSAAccept
(2) I had to call WSAResetEvent( &eventObject) as I mentioned above
(3) I had to set the last argument of  WSAWaitForMultipleEvents to TRUE.

Case 3 really had nothing to do with my problem. It had to do with the fact that I use WSARecv in non-blocking mode and if you don't set the last argument to TRUE, the lpCompletionROUTINE in WSARecv will not get called. When it does get called, WSAWaitForMultipleEvents will return with WAIT_IO_COMPLETION.

I'm giving AlexFM credit because he at least confirmed that I had the right idea which itself was very important to me.
0
 

Author Comment

by:ESQuicksall
ID: 12896192
So, here is the correct code:

WSAStartup(0x202, &wsaData);
listenSocket = WSASocket(AF_INET, DEFAULT_PROTO, 0, NULL, 0, dwFlags);
bind(listenSocket, (struct sockaddr*)&local, sizeof(local);
listen(listenSocket, SOMAXCONN);
eventObject  = WSACreateEvent();
WSAEventSelect( listenSocket, eventObject, FD_ACCEPT );
for (;;)
{
    do {
        rc = WSAWaitForMultipleEvents( 1, &eventObject, FALSE, WSA_INFINITE, TRUE );
    } while (rc != WAIT_IO_COMPLETION);
    fromlen = sizeof(from);
    socket = WSAAccept(listenSocket, (struct sockaddr *)&from, &fromlen, conditionFunc, 0); // conditionFunc returns CF_ACCEPT
    WSAResetEvent( &eventObject );
    WSARecv(,,,,,, TOEHW_RecvComplete);
   // a call to TOEHW_RecvComplete should occur after calling WSAWaitForMultipleEvents when it blocks
}
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 13027152
ESQuicksall,
Thanks for finalizing this and providing such a good explanation of the solution you found. :-)
-- Dan
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows a few slightly more advanced techniques for Windows 7 gadget programming, including how to save and restore user settings for your gadget and how to populate the "details" panel that is displayed in the Windows 7 gadget gallery.  …
With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Integration Management Part 2

580 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question