André Caron
André Caron

Reputation: 45254

TCP shutdown with sockets connected through AcceptEx()

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)?

Upvotes: 9

Views: 2657

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597186

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().

Upvotes: 11

Related Questions