In C#
, if I close a NetworkStream
that was instantiated from TCPClient.GetStream()
, it disconnects my TCP client.
Take this code for example:
TcpClient tcpClient = new();
IPEndPoint ipEndPoint = new(IPAddress.Parse("xxx.xxx.xx.xx"), 1026);
tcpClient.Connect(ipEndPoint);
Console.WriteLine($"Before open stream: tcpClient.Connected == {tcpClient.Connected}");
NetworkStream stream = tcpClient.GetStream();
Console.WriteLine($"After get stream: tcpClient.Connected == {tcpClient.Connected}");
stream.Close();
Console.WriteLine($"After close stream: tcpClient.Connected == {tcpClient.Connected}");
tcpClient.Close();
The above code gives me this result:
Before open stream: tcpClient.Connected == True
After get stream: tcpClient.Connected == True
After close stream: tcpClient.Connected == False
Could someone explain to me why this happens? Or maybe explain (for dummies) how TcpClient
and its NetworkStream
are related such that this should work this way?
CodePudding user response:
I think, it is because it is reasonable to close the entire connection once the stream is closed. When we take a look into the source code of TcpClient we can see the following implementation:
https://github.com/microsoft/referencesource/blob/master/System/net/System/Net/Sockets/TCPClient.cs
public NetworkStream GetStream() {
if(Logging.On)Logging.Enter(Logging.Sockets, this, "GetStream", "");
if (m_CleanedUp){
throw new ObjectDisposedException(this.GetType().FullName);
}
if (!Client.Connected) {
throw new InvalidOperationException(SR.GetString(SR.net_notconnected));
}
if (m_DataStream==null) {
m_DataStream = new NetworkStream(Client, true);
}
if(Logging.On)Logging.Exit(Logging.Sockets, this, "GetStream", m_DataStream);
return m_DataStream;
}
It says new NetworkStream(Client, true)
.
According to https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.networkstream.-ctor?view=net-6.0#system-net-sockets-networkstream-ctor(system-net-sockets-socket-system-boolean) the second argument is ownsSocket
.
Under Remarks, the following is stated:
If the value of ownsSocket parameter is true, the NetworkStream takes ownership of the underlying Socket, and calling the Close method also closes the underlying Socket.
So closing the underlying socket means, that the connection is closed, and therefore TcpClient.Connected
is false
.