IOCP AcceptEx does not generate completion on connect

I am currently trying to create several new libraries (IOCP) for socket programming. And I came across AcceptEx for enabling asynchronous connections.

As the documentation says:

The AcceptEx function uses overlapping I / O, unlike the accept function. If your application uses AcceptEx, it can serve a large number of clients with relatively few threads. As with all overlapping Windows functions, you can use either Windows events or completion ports as the completion notification mechanism.

But I am not getting any completion when the client connects. However, I am getting completion when the client sends data.

This is my code:

DWORD dwBytes;
GUID GuidAcceptEx = WSAID_ACCEPTEX;
int iResult = WSAIoctl(m_hSocket, SIO_GET_EXTENSION_FUNCTION_POINTER,
    &GuidAcceptEx, sizeof (GuidAcceptEx), 
    &m_lpfnAcceptEx, sizeof (m_lpfnAcceptEx), 
    &dwBytes, NULL, NULL);

if (iResult == SOCKET_ERROR)
{
    CloseSocket();
}

      

And then:

WSAOVERLAPPED olOverlap;
memset(&olOverlap, 0, sizeof (olOverlap));
char lpOutputBuf[1024];
int outBufLen = 1024;
DWORD dwBytes;

BOOL bRet = m_lpfnAcceptEx( m_hSocket, hSocket, lpOutputBuf,
             outBufLen - ((sizeof (sockaddr_in) + 16) * 2),
             sizeof (sockaddr_in) + 16, sizeof (sockaddr_in) + 16, 
             &dwBytes, &olOverlap);
if ( bRet == FALSE )
{
    DWORD dwRet = WSAGetLastError();
    if( dwRet != WSA_IO_PENDING )
    {
        return dwRet;
    }
}

      

Any suggestion on what to do to get revisions?

EDIT: I am binding hSocket to the terminating port after m_lpfnAcceptEx ()

+1


source to share


1 answer


First, WSAOVERLAPPED

and the data buffer that you declare on the stack above the call AcceptEx()

will not exist when completion occurs (unless you call GetQueuedCompletionStatus()

into the same function, which is odd nothing). You need to dynamically allocate them or combine them.

Second, you specify that you bind the socket to the completion port after the call AcceptEx()

. It is not right. You need to do this before calling AcceptEx()

.

  • Create a socket with WSA_FLAG_OVERLAPPED

    .
  • Link it to the address you want to listen to.
  • Call a listener with the request you want.
  • Load AcceptEx()

    dynamically with a listening socket and call WSAIoctl

    (not required and the code you are showing should work, but this way you can be sure to get your listening socket from the same main winsock service provider and it supports AcceptEx ( ).
  • Download the GetAcceptExSockaddrs()

    same way as you download AcceptEx()

    - you will need it after the reception is complete.
  • Bind the auditory socket to the IOCP.

You can now send multiple calls AcceptEx()

using the listening socket and the new "accept" socket, which you create like this:

  • Create a socket with WSA_FLAG_OVERLAPPED

    .
  • Bind the socket to the IOCP.

As stated above, you need to make sure the buffer and OVERLAPPED are unique for each call and last until completion occurs.



When completion occurs, you must do the following ....

  • Call setsockopt()

    with SO_UPDATE_ACCEPT_CONTEXT

    on a received socket using the listening socket as data ...
  • Unblock your addresses using GetAcceptExSockaddrs()

    .
  • Process any data (if you have allocated enough buffer space for the data).

Note that by design AcceptEx()

it can be used to accept a new connection and return the original data from that connection in a single operation (this leads to slightly better performance in situations where you know you will always want to get some data before you can start doing what something, but terribly difficult to manage if you want to protect against a denial of service attack that can be launched by simply connecting and NOT sending data - I wrote about it here ).

If you don't want to AcceptEx()

wait until the data is received, simply specify a data buffer that is ONLY large enough for the returned addresses and passes 0 as the "buffer size". This will cause it AcceptEx()

to run as overlapped accept()

and will return as soon as the connection is established.

Please note that Martin James's initial comment on your question is actually the answer you are looking for. Don't miss it outBufLen - ((sizeof (sockaddr_in) + 16) * 2)

, go through 0

.

+9


source







All Articles