问题
I'm now working on a tcp socket connection to tcp server running in ESP32. It works fine for the communication, but I failed to close the connection. After searching for the solution on close/reset tcpClient, it seems that the proper way to close a tcpClient should be:
tcpClient.GetStream().Close();
tcpCLient.Close();
The example in msdn also use this method.
But unforunately, it cannot really close the connection. As checked in the mcu, the connection has not been closed. And it will not be closed even I close the application later. In this case, the mcu's tcp connection cannot be released, it cannot receive other connections. So, I think this should not be a proper solution to close the tcpClient.
If I did not execute above statement, and close the application directly, it can close the connection successfully. And the mcu's tcp connection is released. It seems that the there has something been done in application close which can really close the connection.
In some situation, I need to close the connection after some operation, and reconnect it. So, I cannot rely on the application close.
I have tried all the following methods in some different combination, but none of them can successfully release the tcpClient connection:
tcpClient.Close();
tcpClient.Client.Close();
tcpClient.GetStream().Close();
tcpClient.Client.Disconnect(true);
tcpClient.Client.Disconnect(false);
tcpClient.Dispose();
tcpClient.Client.Dispose();
tcpCLient = null;
Maybe it should be done with some of above commands in a proper sequence.
Does anyone know how I cannot close the connection by myself.
Thanks in advance.
回答1:
After studying the network packet using WireShark, it was found that the problem is due to the delay of sending RST with the code as suggested in MSDN:
tcpClient.GetStream().Close();
tcpCLient.Close();
There has no different even adding
tcpClient.LingerState = new LingerOptions(true, 0);
Because it will send FIN immediately, but not the RST after the Close method, it will be sent around 2 minutes later. Unfortunately, it won't be sent even you close the application after tcpClient close is issued.
If you close the application before closing the tcpClient, it will send the RST immedicately.
So that it can close the connection in server immediately.
After testing different combination of command, it was found that the following code can really close the connection immediately, but there will have another RST around 40 seconds later.
tcpClient.Client.Close();
tcpClient.Close();
Don't call tcpClient.GetStream().Close(); !!! It will cause the delay of RST.
I don't know if there has any impact closing the connection in this way, but this is the only way I can really close the connection immediately.
回答2:
As you mentioned, this is the correct way to close a TcpClient:
tcpClient.GetStream().Close();
tcpCLient.Close();
Close()
will eventually close the connection. Take a look at the documentation for TcpClient.Close()
The Close method marks the instance as disposed and requests that the associated Socket close the TCP connection. Based on the LingerState property, the TCP connection may stay open for some time after the Close method is called when data remains to be sent. There is no notification provided when the underlying connection has completed closing.
You may be able to get the behavior you desire by changing the LingerState property of the TcpClient
object.
tcpClient.LingerState = new LingerOptions(true, 0);
来源:https://stackoverflow.com/questions/51215320/what-should-i-do-to-completely-close-the-tcpclient-connection-with-mcu