Solved

Using WSAEventSelect and WSAWaitForMultipleEvents

Posted on 2004-10-30
2,459 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
Question by:ESQuicksall
    15 Comments
     

    Author Comment

    by:ESQuicksall
    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:
    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
    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
     

    Author Comment

    by:ESQuicksall
    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
    AlexFM, do you have any other ideas as to what is going on?

    Eddy
    0
     

    Author Comment

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

    Author Comment

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

    Author Comment

    by:ESQuicksall
    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
    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
    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

    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
    It turns out that that bug correction did not help. So, I'm still stuck.
    0
     

    Author Comment

    by:ESQuicksall
    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
    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
    ESQuicksall,
    Thanks for finalizing this and providing such a good explanation of the solution you found. :-)
    -- Dan
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone. Privacy Policy Terms of Use

    Featured Post

    Highfive + Dolby Voice = No More Audio Complaints!

    Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

    Suggested Solutions

    This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
    As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
    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…
    Want to pick and choose which updates you receive? Feel free to check out this quick video on how to manage your email notifications.

    877 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

    Need Help in Real-Time?

    Connect with top rated Experts

    13 Experts available now in Live!

    Get 1:1 Help Now