在远程客户端调用 Dispose() 后仍然能够从 TCPClient 检索流

Still able to retrieve Stream from TCPClient after remote client has called Dispose()

我有一个简单的客户端/服务器项目,都运行在我的本地机器上。

在我的客户端项目中,我能够运行以下(简化的)测试代码:

using(var tcpClient = new System.Net.Sockets.TCPClient())
{
  tcpClient.ConnectAsync(host, port).Wait(Timespan.FromSeconds(3));
  using (NetworkStream ns = tcpClient.GetStream())
  {
    ns.Write("Hello World", 0, "Hello World".Length);
    Thread.Sleep(100);
  }
}

这应该将“Hello World”写入流,然后在约 100 毫秒后处理所有内容,因此在此之后它无法读取。

问题是,我的服务器项目中的 TcpListener 运行ning 能够大致执行以下操作:

TcpClient client = TcpListener.AcceptTcpClient();
Thread.Sleep(750);
var stream = client.GetStream();  //I am still able to read the contents of this - shouldnt it be closed?

这可能是由于 运行 在同一台机器上安装 client/server 造成的问题吗?还是我对客户端上的 Dispose() 调用有根本性的误解。

do I have a fundamental misunderstanding of the Dispose() calls made on the client.

你看起来确实如此。

Disposing a TcpClient() for which GetStream() has been called disposes that local NetworkStream. In turn, disposing that stream 在底层套接字上调用 Shutdown(),然后关闭套接字,释放它的本机句柄。 (如果还没有创建流,后两个操作将在 TcpClient 中执行。也就是说,无论如何它们都会发生。)

就是这样。没有别的。

如果您已经在套接字上发送了数据(并且您已经发送),然后等待足够长的时间来传输该数据(并且您已经发送),那么数据将不再由您控制。事实上,从概念上讲,当你把它交给插座时,它就不再受你控制了。即使在某些情况下您能够足够快地摆脱套接字以防止发送数据,您也不应指望这一点。在实践中,网络驱动程序通常会非常努力地传输他们收到的任何数据,无论本地套接字端发生什么。

所以,是的。如果您期望在发送数据后关闭本地套接字会以某种方式影响远程端点是否能够接收您已发送的数据,那么您实际上对 Dispose() 在客户端(本地套接字)上进行的调用。