NetworkStream异常和返回代码

时间:2015-02-12 18:22:59

标签: c# async-await tcpclient networkstream

我试图教育自己从NetworkStream阅读的复杂性,并了解可能出现问题的各种方式。我有以下代码:

    public async Task ReceiveAll()
    {
        var ns = this.tcp.GetStream();
        var readBuffer = new byte[1000];
        while (true)
        {
            int bytesRead;
            try
            {
                bytesRead = await ns.ReadAsync(readBuffer, 0, readBuffer.Length);
                if (bytesRead == 0)
                {
                    // Remote disconnection A?
                    break;
                }
            }
            catch (IOException)
            {
                // Remote disconnection B?
                break;
            }
            catch (ObjectDisposedException)
            {
                // Local disconnection?
                break;
            }

            /*Do something with readBuffer */
        }
    }

我在代码中标记了三个点,程序说“有些东西出了问题,没有必要继续下去”。

'本地断开连接'并非完全错误,当我在本地关闭套接字时会发生这种情况,这是在正常情况下退出循环的唯一方法。我认为其他任何事情都不会导致这种情况发生,所以我认为我可以安全地接受这个例外。

两个'远程断开连接'积分是我不确定的。我知道如果远程终止连接,ReadAsync将返回0(A),但在某些情况下似乎也会触发IOException。如果我的远程客户端是C#控制台,那么关闭套接字似乎会使A' A'发生了,并关闭控制台窗口似乎是' B' B' B'发生。我不确定我理解这些场景之间的区别是什么?

最后,这是一个普遍的问题,但是这些代码或我的上述假设是否有任何明显的错误?

感谢。

编辑:响应我使用ObjectDisposedException中止循环:

这就是我的停止'方法看起来像(与上面相同的类):

    public void Stop()
    {
        this.tcp.Close();
    }

这导致待处理的' ReadAsync'与ObjectDisposedException除外。 AFAIK没有任何其他方法可以中止这一点。将此更改为:

    public void Stop()
    {
        this.tcp.Client.Shutdown(SocketShutdown.Both);
    }

似乎没有对待处理的电话做任何事情,它只是继续等待。

1 个答案:

答案 0 :(得分:2)

NetworkStream返回0时,这表示套接字已从远程方收到断开连接数据包。这就是网络连接的结束方式。

关闭连接的正确方法(特别是在进行全双工对话时)是拨打socket.Shutdown(SocketShutdown.Send)并让远程方有时间关闭其发送频道。这可确保您收到任何待处理数据,而不是关闭连接。 ObjectDisposedException永远不应成为正常申请流程的一部分。

抛出的任何异常都表明出现了问题,我认为可以说你不能再依赖当前的连接了。

TL; DR

我没有看到您的代码有任何问题,但(特别是在全双工通信中)我会关闭发送通道并等待0字节数据包以防止默认接收ObjectDisposedException

  1. 使用tcp.Shutdown(SocketShutdown.Send)告诉要断开连接的远程方

  2. 您的循环可能仍会收到远程方正在发送的数据

  3. 如果一切正常,你的循环将接收一个0字节的数据包,表明远程方正在断开连接

  4. 循环以正确的方式终止

  5. 如果你没有收到0字节的数据包,你可能想在一段时间后决定处理套接字