C# 在远程客户端调用Dispose()后,仍然能够从TCPClient检索流
我有一个简单的客户机/服务器项目,两者都在本地机器上运行 在我的客户机项目中,我能够运行以下(简化的)测试代码:C# 在远程客户端调用Dispose()后,仍然能够从TCPClient检索流,c#,.net,tcpclient,C#,.net,Tcpclient,我有一个简单的客户机/服务器项目,两者都在本地机器上运行 在我的客户机项目中,我能够运行以下(简化的)测试代码: using(var tcpClient = new System.Net.Sockets.TCPClient()) { tcpClient.ConnectAsync(host, port).Wait(Timespan.FromSeconds(3)); using (NetworkStream ns = tcpClient.GetStream()) { ns.Wri
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”写入流,然后在~100ms后处理所有内容,因此在这一点之后将无法读取
问题是,在我的服务器项目中运行的TcpListener
大致可以执行以下操作:
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?
这可能是在同一台计算机上运行客户机/服务器引起的问题吗?或者我对客户端上的Dispose()
调用有根本性的误解
我是否对客户机上的Dispose()
调用有根本性的误解
你看起来确实是
为其调用的GetStream()
将处理本地NetworkStream
。依次调用底层套接字上的Shutdown()
,然后关闭套接字,释放其本机句柄。(如果尚未创建流,则后两个操作将在TcpClient
中执行。也就是说,不管发生什么,它们都将始终发生。)
就这些。没有别的了
如果您已经在套接字上发送了数据(并且您已经发送了),然后等待数据传输的时间足够长(并且您已经发送了),那么数据将不再在您的控制范围内。事实上,从概念上讲,当你把它放到插座上时,它就不再在你的控制之下了。即使在某些情况下,您能够足够快地摆脱套接字,以防止数据被发送,您也不应该指望这一点。在实践中,无论本地套接字端发生什么情况,网络驱动程序通常都会非常努力地传输所提供的任何数据
所以,是的。如果您认为在发送数据后关闭本地套接字会以某种方式影响远程端点是否能够接收您已经发送的数据,那么实际上您对客户端(本地套接字)上的
Dispose()
调用有一个基本的误解.我是否对Dispose()调用有一个根本性的误解。您处理的是tcpClient
的实例,而不是其他任何东西。这不会撤销已发送的字节,也不会向服务器发送一条比光速更快的消息,以停止读取任何可能正在读取的内容。我相信您的数据实际上已经发送,因此GetStream
只会在接收到的rx套接字缓冲区数据上创建流。@Gserg GetStream()在客户端中释放网络流和客户端后调用?您已经释放了连接的一端。您尚未使服务器上网卡缓冲区的内容无效。在哪里关闭流。。。您的第一个方法是AcceptCpcClient的表示吗?谢谢您的超级答案。在读取流之后,是否可以从服务器检查调用TCPClient的状态?(以确定它是否仍然存在)作为一般规则,否。本地端点几乎没有关于远程端点状态的信息。如果远程端点已关闭和/或关闭套接字,则本地端点可以发现这一点,即发送数据的尝试将因异常而失败,读取操作将以0字节长度完成,或因异常而失败。但是一旦这些事件发生,本地端点关于远程端点状态的任何知识都将结束。