网络流如何检测断开连接

时间:2016-09-03 10:03:21

标签: c# sockets asynchronous tcp network-programming

我最近开始研究套接字编程并编写了一个简单的异步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 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中检测断开的套接字应该不那么容易)

我做错了什么?

3 个答案:

答案 0 :(得分:1)

您应该将.ReadAsync()与cancellationToken一起使用。然后更改循环以检查标记值。当您要杀死客户端时,您会发信号通知令牌。

同时检查变量bytesRead。如果它返回0,则连接刚刚关闭。

答案 1 :(得分:1)

  让我心烦的是,无论我如何摧毁客户端   (查杀进程和...)ReadAsync方法立即抛出一个   例外

欢迎使用网络(套接字)编程。您可以对这些异常做好准备,因为在这些类型的应用程序中遇到异常是很常见的。这种行为是设计使然。

应该在最终用户得到好消息的情况下开发你的应用程序,而不是异常消息。

  

... ReadAsync方法立即抛出异常   基本上与我的想法发生冲突(据我读过检测   在tcp中断开连接的套接字应该不那么容易)

原因是:

TcpClient.Connected Property获取上次I / O操作时Client套接字的连接状态。当它返回false时,客户端套接字从未连接,或者不再连接。

由于Connected属性仅反映最近一次操作时的连接状态,因此您应尝试发送或接收消息以确定当前状态。 消息发送失败后,此属性不再返回true。

请注意,此行为是设计使然。您无法可靠地测试连接状态,因为在测试和发送/接收之间的时间内,连接可能已丢失。您的代码应该假定套接字已连接,并正常处理失败的传输。

答案 2 :(得分:0)

它不是“检测”断开连接,它是trhows和exception,因为.ReadAsync一直试图获取是否有可读取的数据,如果有写入缓冲区,如果数据长度==缓冲区长度然后结束功能。所有这些步骤(可能还有更多)涉及Stream,它绑定到socket。然后,如果套接字关闭(通过代码或手动),则关闭流,如果您尝试对关闭的流执行任何操作,则会抛出异常。