title: Unable to accept a new connection properly using IOCP - Invalid socket handle
body: <p>I am learning about IOCP and have decided to write my own wrapper class based on the following article:<br>
  <a href="http://www.codeproject.com/Articles/13382/A-simple-application-using-I-O-Completion-Ports-an" rel="nofollow">http://www.codeproject.com/Articles/13382/A-simple-application-using-I-O-Completion-Ports-an</a></p>
  
  <p>My project is a C++ TCP server using IOCP. The client uses send() and recv() to send and receive data which I cannot change (from what I've been told this shouldn't cause any problem, but I am mentioning it just in case). It also creates a socket using socket() (and not WSASocket()).
  Everything seems to be working fine (no error with CreateIoCompletionPort, I can add a socket descriptor to the existing completion port without any error. I've checked everything by adding a call to WSAGetLastError() after each of these functions).  </p>
  
  <p>(Before anything, please don't mind the inconsistent coding style. I like to make stuff work first and then clean it all up.)</p>
  
  <pre><code>socket_ = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
  setsockopt(socket_, IPPROTO_IP, SO_DEBUG | TCP_NODELAY, sockopt, 4);
  ioctlsocket(socket_, FIONBIO, &amp;ulSockMode_);
  sin_.sin_family = AF_INET;
  sin_.sin_port = htons((uint16_t)uiPort_));
  hAccept_[0] = WSACreateEvent();  //only 1 event, I'm using an array for convenience
  
  if (hAccept_ == WSA_INVALID_EVENT)
  {
      //this is never executed
  }
  WSAEventSelect(socket_, hAccept_[0], FD_ACCEPT);
  </code></pre>
  
  <p>After an incoming connection is detected (I use WSAWaitForMultipleEevents and WSAEnumNetworkEvents which work don't trigger any error), I use the following code to accept the client (and this is where the problems start):</p>
  
  <pre><code>SOCKET sock_client{ INVALID_SOCKET };
  int32_t len_si{ sizeof(SOCKADDR_IN) };
  //sock_client = accept(socket_, reinterpret_cast&lt;SOCKADDR*&gt;(pSockAddr), &amp;len_si); // this works fine
  //sock_client = sock_client = WSAAccept(socket_, reinterpret_cast&lt;SOCKADDR*&gt;(pSockAddr), &amp;len_si, NULL, 0);//works fine too
  char buf[2 * (sizeof(SOCKADDR_IN) + 16)];
  WSAOVERLAPPED wsaovl;
  uint32_t bytes{ 0 };
  BOOL b = AcceptEx(socket_, sock_client, (PVOID)buf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, reinterpret_cast&lt;LPDWORD&gt;(&amp;bytes), &amp;wsaovl); //this fails, returns 0
  int32_t test = WSAGetLastError(); // this returns 6 (WSA_INVALID_HANDLE)
  </code></pre>
  
  <p>I have no idea why it works with accept() and WSAAccept(), however it doesn't with AcceptEx().</p>
  
  <p>If I use accept() though, after accepting the client I need to call WSARecv() immediately. I'm not sending anything back to the client just yet but I read that it needs to be called before GetQueuedCompletionStatus() in the worker thread: </p>
  
  <pre><code>WSABUF* buf = new WSABUF;
  OVERLAPPED* ovl = new OVERLAPPED;
  int32_t flags{ 0 };
  int32_t bytes{ 0 };
  int32_t bytes_recv = WSARecv(client_socket, buf, 1, &amp;flags, &amp;bytes, ovl, NULL); // this returns -1
  int32_t err = WSAGetLastError(); // this returns 6 (WSA_INVALID_HANDLE)
  </code></pre>
  
  <p>And since this doesn't work, the GetQueuedCompletionStatus() routine in my worker thread keeps on hanging (or at least, I assume this is the reason)</p>
  
  <p>Is there anything wrong with what I'm doing? I've been trying to search around and fix it since yesterday night, I know it's not a lot of time but I really don't see what I'm not doing correctly.</p>
  
  <p>UPDATE:
  I have changed the way I initialize my socket for AcceptEx().  </p>
  
  <pre><code>SOCKET sock_client = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
  </code></pre>
  
  <p>and  </p>
  
  <pre><code> WSAOVERLAPPED wsaovl = {};
  </code></pre>
  
  <p>AcceptEx() still returns false, however the error returned by WSAGetLastError() is now 997 (WSA_IO_PENDING). I'm not sure what I/O operation is pending exactly and how I would go about fixing it.</p>