8

The documentation for AcceptEx() says:

When this operation is successfully completed, sAcceptSocket can be passed, but to the following functions only:

  • ReadFile
  • WriteFile
  • send
  • WSASend
  • recv
  • WSARecv
  • TransmitFile
  • closesocket
  • setsockopt (only for SO_UPDATE_ACCEPT_CONTEXT)

Notice that shutdown() is not in the list. Indeed, invoking shutdown(sAcceptSocket, SD_SEND) returns SOCKET_ERROR and WSAGetLastError() produces error WSAENOTCONN:

A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

Why can you not shutdown a socket connected through AcceptEx()? Also, why does the socket not appear as connected since it is already receiving data (the overlapped operation has completed and the completion notification indicates that some size>0 bytes were received)?

André Caron
  • 44,541
  • 12
  • 67
  • 125
  • The client haven't already closed the connection? Do you get the same error if you do `shutdown` directly after `AcceptEx`? – Some programmer dude Feb 07 '12 at 07:35
  • @JoachimPileborg: No, the client has not closed the connection. I'm testing with accepting HTTP requests from Chrome with the "Connection: keep-alive" header. I get this error whether I send data or not. – André Caron Feb 07 '12 at 17:27

1 Answers1

10

You have to call setsockopt(SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT) after AcceptEx() completes. The accepted socket is not fully associated with the properties of the listening socket, and as such will not be in a fully connected state, until SO_UPDATE_ACCEPT_CONTEXT is set. Some winsock API functions are affected by that, including getpeername(), getsockname() and shutdown().

If you use ConnectEx() to make an outbound connection, you have to invoke setsockopt(SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT) after ConnectEx() completes before you can then use shutdown(). This is documented behavior on MSDN. It does not say the same for AcceptEx() and SO_UPDATE_ACCEPT_CONTEXT, but shutdown() does have a similar restriction for sockets accepted by AcceptEx().

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I'm already calling `setsockopt()` to make sure that `getpeername()` *et al.* work as expected. Let me run some tests, I'll get back to you on this issue. – André Caron Feb 07 '12 at 17:29
  • I'm not sure in which order I original tested, but it works now. If I remove the call to `setsockopt()`, I get an error again. Thanks a lot! – André Caron Feb 07 '12 at 18:02