Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent .NET libraries from sending RST packet on close

Tags:

c#

.net

sockets

I'm doing some testing trying to isolate some odd behavior in the libraries (.NET). When I use the Winsock API through C++ and simply call, closesocket(), I see the windows side send the FIN/ACK packet and the remote side send back an ACK packet. This is what I would call a graceful close. However, when programming in C# I'm not seeing what I would call a graceful close.

In C#, I open my socket and then, when closing it, I see windows send a FIN packet Only when first calling Socket.Shutdown(). However, regardless, when I call Socket.Close() in C#, an RST packet is sent and the connection summarily dropped. This confuses me because, from what I've read on line, the TCP closing process should be FIN/ACK -> ACK (from both sides actually but for now, I'm only concerned with "my" side); i.e. there should not be an RST packet in the mix at all. From what I've read, apparently, an RST packet is only sent when the receiver is uncertain about the connection state and wants out.

Why is this RST packet being sent on a planned shutdown in .NET and not at all in a planned shutdown from the winsock API? Is there a way to prevent the transmission of an RST packet during a graceful shutdown from .NET?

In case it's important, in both code paths, I'm reading all available data on the socket before calling the respective close() method.

like image 831
Andrew Falanga Avatar asked Aug 23 '11 17:08

Andrew Falanga


2 Answers

Reading the .NET doc of Socket.Close, this is what I found:

For connection-oriented protocols, it is recommended that you call Shutdown before calling the Close method. This ensures that all data is sent and received on the connected socket before it is closed. If you need to call Close without first calling Shutdown, you can ensure that data queued for outgoing transmission will be sent by setting the DontLinger Socket option to false and specifying a non-zero time-out interval. Close will then block until this data is sent or until the specified time-out expires. If you set DontLinger to false and specify a zero time-out interval, Close releases the connection and automatically discards outgoing queued data.

which actually makes sense. If there's still data in the buffer (OS one) and you tear the connection down or kill the process the connection will be reset (more detailed information in the TCP specs).

As to when RST is sent check out TCP Guide.

My guess is that there is still some unset or in transit data or in outgoing/incomming buffers that triggers the RST.

like image 145
Boklucius Avatar answered Oct 17 '22 01:10

Boklucius


Following code may prevent RST packet. It is because wait 60 seconds after sending a FIN packet.

socket.Close(60);

Close method description is here.

like image 20
constdrop Avatar answered Oct 17 '22 01:10

constdrop