CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Jan 2010
    Posts
    20

    Event is not signaled on non-blocking socket

    Hi All

    I have a non-blocking socket and I'm working with event objects. I'm on the client side. I'm implementing a hand-shake protocol. It's fairly straightforward, I connect to the server, I send query1, I receive resp1, I send query2, I receive resp2, and so on, it's a 4-5 way ping-pong like messaging. I'm not happy with it either but I have to live with it.

    My problem is, after 4 rounds of send-recv, WSAWaitForMultipleEvents() wouldn't return.

    Following is a representation of what I do in my code
    Code:
    event = CreateEvent(...)
    sock = WSASocket(...., WSA_FLAG_OVERLAPPED)
    WSAEventSelect(sock, event, FD_CONNECT)
    WSAWaitForMultipleEvents(1, event, ...)  // this one is ok
    WSAEnumNetworkEvents(sock, event, &networkEvents)
    and my client has connected to the server. Now I send something, select read and close events, and then sit in a loop
    Code:
    send(...)
    WSAEventSelect(sock, event, FD_CLOSE | FD_READ)
        loop()
        {
        WSAWaitForMultipleEvents(...INFINITE)  // this one stucks after three iterations
        ...
        WSAEnumNetworkEvents(sock, event, &networkEvents)
        ...
        }
    Ok, it's a bit more complicated than that. I take care of WSAEWOULDBLOCK cases. And there is another event to signal thread termination so WSAWaitForMultipleEvents would return to exit loop.

    After each send() completes I call WSAEventSelect(sock, event, FD_CLOSE | FD_READ), and after each recv() completes I call WSAEventSelect(sock, event, FD_CLOSE | FD_WRITE), and I expect to be notified when there is something to be read on the socket, or the socket is ready for writing.

    My problem : connect - send - recv - send - recv - stuck.

    I tell the socket provider that I want to be niotified when it's ready for writing but it notifies me once for the second send, and the next recv works too, but then it's stuck and I'm not notified for write readiness.

    Has anyone any ideas, apart from the design of the call flow?

    Thanks

  2. #2
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556

    Re: Event is not signaled on non-blocking socket

    There ordinarily is no need to change the events for which you want notification. Call WSAEventSelect once only and ask for notification of all different events.

    Also, remember that WSAEnumNetworkEvents will return ALL events for which the socket is signalled. Thus, it is possible that more than one event will be found inside the WSANETWORKEVENTS structure. Go carefully through each of its pertinent bits, one by one, to ensure that all network events are handled. It's possible, for example, that you are receiving two events at once, but are ignoring one of them.

    If you are still having trouble, show more code.

    Mike

  3. #3
    Join Date
    Jan 2010
    Posts
    20

    Re: Event is not signaled on non-blocking socket

    Mike thanks for the reply. I don't call WSAEventSelect() once for all events because I don't want to be notified non-stop that the socket is ready for writing. I only need to send four messages to the server, and after that I'm done with sending.

    My understanding is that, if I set FD_WRITE bit to WSAEventSelect(), then WSAWaitForMultipleEvents() will return, with the network event handle set, every time writing is possible on the socket. I don't what that, this is why I switch lNetworkEvents parameter to WSAEventSelect() from FD_CLOSE | FD_WRITE to FD_CLOSE | FD_READ when I don't need to send something to the server.

    Could someone tell me if the way I think above is wrong? I do the same when I set the socket descriptors for select(). I FD_SET the write fd for the socket when I have something to send; otherwise I FD_ZERO the write fd and I leave it at that.

    I already check if the events have been recorded after WSAEnumNetworkEvents() returns. And all the bits have their own if(networkEvents.lNetworkEvents & FD_XXX) clause. And the if()s are stand-alone if()s, not if()...else if()s.

    I haven't abandoned the thread. I know I must be doing something wrong. I believe that regardless of bad design of the code, once I set FD_CLOSE | FD_WRITE in WSAEventSelect(), the WSAWaitForMultipleEvents() function must return sooner or later. But this is where this function is, and also I am, stuck.

  4. #4
    Join Date
    Nov 2002
    Location
    California
    Posts
    4,556

    Re: Event is not signaled on non-blocking socket

    Quote Originally Posted by stolencoin View Post
    ...My understanding is that, if I set FD_WRITE bit to WSAEventSelect(), then WSAWaitForMultipleEvents() will return, with the network event handle set, every time writing is possible on the socket. ...
    This in an incorrect understanding of the write event. FD_Write is signalled only once when the socket becomes writable. After that, it does not become signalled again until after a send() has been called that fails with a GetLastError of WSAEWOULDBLOCK, and then only after the socket again becomes writable.
    Quote Originally Posted by documentation for WSAEventSelect
    The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with a call to the connect, ConnectEx, WSAConnect, WSAConnectByList, or WSAConnectByName function or when a socket is accepted with accept, AcceptEx, or WSAAccept function and then after a send fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the application will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is set.
    Again, for many many situations, the best advice is to call WSAEventSelect() once for all events, and not to call it again. It's not the best advice for all situations, but it would probably work fine in yours.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured