I have a server application that uses IOCP. I want to know what is the proper way to close a SOCKET
.
If I simply call closesocket()
(for a SOCKET
with a handle of for example 12345
), and this SOCKET
has pending IO operations (for example: a pending WSARecv()
request), then the following scenario could happen:
I call
closesocket()
which will destroy theSOCKET
.I accept another
SOCKET
with the same handle of12345
.I deque the pending
WSARecv()
completion packet for theSOCKET
with the handle of12345
. Now I would assume that this completion packet is for the currentSOCKET
with the handle of12345
, but in fact it is for theSOCKET
that was previously closed (this is he main problem with this approach).
So this is obviously a bad approach.
The second approach that seems correct is the following:
I associate a
struct
instance with eachSOCKET
. Thestruct
has the following members: anint
callednumber_of_pending_IO_operations
, and aboolean
calledIs_SOCKET_being_closed
.When I issue an IO operation for the
SOCKET
(for example: aWSASend()
request), I incrementnumber_of_pending_IO_operations
by1
, and when I deque a completion packet for the SOCKET, I decrementnumber_of_pending_IO_operations
by1
.Now, when I want to close the
SOCKET
, I don't simply callclosesocket()
, but rather I callCancelIOEx()
to cancel all pending IO operations for theSOCKET
, and I also setIs_SOCKET_being_closed
totrue
.When I am about to issue another IO operation (for example: a
WSASend()
request), I would check the value ofIs_SOCKET_being_closed
, and if it istrue
, I would not issue the IO operation.Now I simply wait for all of the completion packets to be dequeued, and when
number_of_pending_IO_operations
reaches0
andIs_SOCKET_being_closed
is set totrue
, I callclosesocket()
.
Of course I would have race conditions, so I would use critical sections.
Is the second approach a correct way to close a SOCKET
, or is there a better way?