Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 961
André Caron Avatar asked Feb 06 '12 23:02

André Caron


1 Answers

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

like image 135
Remy Lebeau Avatar answered Nov 12 '22 13:11

Remy Lebeau