There are 3 different accept
versions in winsock. Aside from the basic accept
which is there for standard compliance, there's also AcceptEx
which seems the most advanced version (due to it's overlapped io capabilities), and WSAAccept
. The latter supports a condition callback, which as far as I understand, allows the rejection of connection requests before they're accepted (when the SO_CONDITIONAL_ACCEPT
option is enabled). None of the other versions supports this functionality.
Since I prefer to use AcceptEx
with overlapped io, I wonder how come this functionality is only available in the simpler version?
I don't know enough about the inner workings of TCP to tell wehter there's actually any difference between rejecting a connection before it has been accepted, and disconnecting a socket right after a connection has been established? And if there is, is there any way to mimic the WSAAccept
functionality with AcceptEx
?
Can someone shed some light over this issue?
In general, connection refused errors are generated during a connect system call when an application attempts to connect using TCP to a server port which is not open.
The common way of terminating a TCP connection is by using the TCP header's FIN flag. This mechanism allows each host to release its own side of the connection individually. Suppose that the client application decides it wants to close the connection. (Note that the server could also choose to close the connection).
A Connection Refused (Hostname) error occurs when: You use the wrong port in the connection string. You connect from a machine that is not in the database's list of trusted sources.
There are three ways a TCP connection is closed: The client initiates closing the connection by sending a FIN packet to the server. The server initiates closing the connection by sending a FIN packet to the client. Both client and server initiate closing the connection.
When a connection is established, the remote end sends a packet with the SYN flag set. The server answers with a SYN,ACK packet, and after that the remote end sends an ACK packet, which may already contain data.
There are two ways to break a TCP connection from forming. The first is resetting the connection - this is the same as the common "connection refused" message seen when connecting to a port nobody is listening to. In this case, the original SYN packet is answered with a RST packet, which terminates the connection immediately and is stateless. If the SYN is resent, RST will be generated from every received SYN packet.
The second is closing the connection as soon as it has been formed. On the TCP level, there is no way to close the connection both ways immediately - the only thing you can say is that "I am not going to send any more data". This happens so that when the initial SYN, SYN,ACK, ACK exchange has finished, the server sends a FIN packet to the remote end. In most cases, telling the other end with FIN that "I am not going to send any more data" makes the other end close the connection as well, and send it's own FIN packet. A connection terminated this way isn't any different from a normal connection where no data was sent for some reason. This means that the normal state tracking for TCP connections and the lingering close states will persist, just like for normal connections.
Now, on the C API side, this looks a bit different. When calling listen()
on a port, the OS starts accepting connections on that port. This means that is starts replying SYN,ACK packets to connections, regardless if the C code has called accept()
yet. So, on the TCP side, it makes no difference whether the connection is somehow closed before or after accept. The only additional concern is that a listening socket has a backlog, which means the number of non-accepted connections it can have waiting, before it starts saying RST to the remote end.
However, on windows, the SO_CONDITIONAL_ACCEPT
call allows the application to take control of the backlog queue. This means that the server will not answer anything to a SYN packet until the application does something with the connection. This means, that rejecting connections at this level can actually send RST packets to the network without creating state.
So, if you cannot get the SO_CONDITIONAL_ACCEPT
functionality enabled somehow on the socket you are using AcceptEx
on, it will show up differently to the network. However, not many places actually use the immediate RST functionality, so I would think the requirement for that must mean a very specialized system indeed. For most common use cases, accepting a socket and then closing it is the normal way to behave.
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