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)?
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With