C# 网络流如何检测断开连接
我最近开始研究socket编程,并编写了一个简单的异步tcp服务器,它可以很好地从各个客户端发送接收。以下是它的简化代码:C# 网络流如何检测断开连接,c#,sockets,asynchronous,tcp,network-programming,C#,Sockets,Asynchronous,Tcp,Network Programming,我最近开始研究socket编程,并编写了一个简单的异步tcp服务器,它可以很好地从各个客户端发送接收。以下是它的简化代码: //accpet loop while (true) { var client = await listener.AcceptTcpClientAsync(); new AppClient(client).Start(); } // and here is the start method in AppClient class public async
//accpet loop
while (true)
{
var client = await listener.AcceptTcpClientAsync();
new AppClient(client).Start();
}
// and here is the start method in AppClient class
public async void Start()
{
/// TcpClient is a class property which is in scope of this method
using (var stream = TcpClient.GetStream())
{
string message = string.Empty;
byte[] buffer = new byte[1000];
int bytesRead = 0;
while (true)
{
try
{
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
break;
}
// decode simple text message
message += Encoding.UTF8.GetString(buffer, 0, bytesRead);
}
}
}
它以单线程方式处理数千个连接,但
让我不安的是,无论我如何破坏客户端(杀死进程和…),ReadAsync方法都会立即抛出一个与我的想法基本冲突的异常。
(据我所知,在tcp中检测断开的套接字应该不是那么容易)
我做错了什么吗?它不是“检测”断开连接,而是显示异常,因为.ReadAsync
不断尝试获取是否有数据可读取,是否有数据写入缓冲区,如果数据长度==缓冲区长度,则结束函数。所有这些步骤(可能还有更多)都涉及流
,它绑定到套接字
。然后,如果套接字已关闭(通过代码或手动关闭),则流已关闭,如果您尝试对关闭的流执行任何操作,则将引发异常 您应该将与cancellationToken一起使用。然后更改循环以同时检查令牌值。当你想杀死客户端时,你就给令牌发信号
同时检查变量bytesRead
。如果返回为0
,则连接刚刚关闭
让我不安的是,无论我如何毁掉客户
(终止进程和…)ReadAsync方法立即抛出
例外情况
欢迎使用网络(套接字)编程。您必须让自己对这些异常感到舒适,因为在这些类型的应用程序中遇到异常是非常常见的。这种行为是故意的
您的应用程序应该在这样的情况下开发:最终用户得到的是好消息,而不是异常消息
…ReadAsync方法立即引发异常,该异常
基本上与我的想法冲突。(据我所知)
tcp中断开连接的套接字不应该那么容易)
原因是:
获取上次I/O操作时客户端套接字的连接状态。当返回false时,客户端套接字要么从未连接,要么不再连接
由于Connected属性仅反映最近一次操作时的连接状态,因此应尝试发送或接收消息以确定当前状态。消息发送失败后,此属性不再返回true
请注意,这种行为是出于设计。您无法可靠地测试连接的状态,因为在测试和发送/接收之间,连接可能已丢失。你的代码应该假设套接字已连接,并能优雅地处理失败的传输。你真的不应该做
catch(Exception ex)
-这是一种反模式。谢谢,我会记住这一点。对于他所做的事情,只要我等待它,就捕捉Exception readasync检查绝对没有错,一旦套接字上的数据可用,就会执行方法id的其余部分。非常感谢取消提示。但是bytesRead从不为零,带有wait的ReadAsync方法会暂停该方法,直到有东西要读取为止。顺便说一句,如果服务器端断开连接,它将返回0。感谢您的响应,在无限循环中使用wait stream.ReadAsync()可以吗?(我这样做是为了不断监听来自客户端的新数据)@SHM-是的,没问题。若客户机发送数据的次数事先不知道,那个么是的,您必须一直等待并接收数据。一旦客户端关闭套接字,您的循环就会中断,从而引发异常。@SHM-另外,请仔细耐心地重新阅读我的答案的最后两段。这些话很有帮助。祝你在网络编程方面的经验好运。是的,我读到了,不管多么优雅地接近=发送一个接近的数据包。现在,如果客户端没有机会将关闭数据包发送到tcp,ReadAsync如何抛出“强制关闭异常”@SHM-如果客户端没有机会将关闭数据包发送到tcp,ReadAsync如何抛出“强制关闭异常”是什么意思?引用MSDN source的话:Close方法将实例标记为已释放,并请求关联的套接字关闭TCP连接。基于LingerState属性,在调用Close方法后,当数据仍有待发送时,TCP连接可能会保持打开状态一段时间。当基础连接完成关闭时,不提供任何通知代码>