NetworkStream 异常和 return 代码
NetworkStream exceptions and return codes
我正在努力自学从 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 */
}
}
我在代码中标记了三个点,其中程序显示 'something has gone awry, there is no point continuing'。
'Local disconnection' 并没有什么问题,当我在本地关闭套接字时会发生这种情况,这是正常情况下退出循环的唯一方法。我认为没有其他原因会导致这种情况,所以我认为我可以安全地吞下这个例外。
这两点'Remote disconnection'是我不确定的地方。我知道如果连接被远程终止 (A),ReadAsync 将 return 0,但 IOException 在某些情况下似乎也会触发。如果我的远程客户端是 C# 控制台,那么关闭套接字似乎会使 'A' 发生,而关闭控制台 window 似乎会使 'B' 发生。我不确定我是否理解这些场景之间的区别?
最后,问一个一般性的问题,但是这段代码或我的上述假设有什么明显的错误吗?
谢谢。
编辑:响应我使用 ObjectDisposedException 退出循环:
这就是我的 'Stop' 方法的样子(来自与上面相同的 class):
public void Stop()
{
this.tcp.Close();
}
这会导致挂起的 'ReadAsync' 异常异常。 AFAIK 没有任何其他方法可以中止它。将其更改为:
public void Stop()
{
this.tcp.Client.Shutdown(SocketShutdown.Both);
}
似乎没有对挂起的呼叫做任何事情,它只是继续等待。
当NetworkStream
returns 0时,表示socket收到了对方发来的disconnect包。这就是网络连接应该如何结束。
关闭连接的正确方法(尤其是在全双工对话中)是调用 socket.Shutdown(SocketShutdown.Send)
并给远程方一些时间来关闭他们的发送通道。这可以确保您收到任何待处理的数据,而不是关闭连接。 ObjectDisposedException
永远不应成为正常申请流程的一部分。
抛出的任何异常都表明出现了问题,我认为可以肯定地说您不能再依赖当前连接。
TL;DR
我没有发现您的代码有任何问题,但是(尤其是在全双工通信中)我会关闭发送通道并等待 0 字节数据包以防止接收 ObjectDisposedException
s默认:
使用tcp.Shutdown(SocketShutdown.Send)
告诉对方你想断开连接
您的循环可能仍会收到远程方正在发送的数据
如果一切正常,你的循环将收到一个 0 字节的数据包,表明对方正在断开连接
循环以正确的方式终止
如果您还没有收到 0 字节数据包,您可能想在一定时间后决定处理套接字
我正在努力自学从 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 */
}
}
我在代码中标记了三个点,其中程序显示 'something has gone awry, there is no point continuing'。
'Local disconnection' 并没有什么问题,当我在本地关闭套接字时会发生这种情况,这是正常情况下退出循环的唯一方法。我认为没有其他原因会导致这种情况,所以我认为我可以安全地吞下这个例外。
这两点'Remote disconnection'是我不确定的地方。我知道如果连接被远程终止 (A),ReadAsync 将 return 0,但 IOException 在某些情况下似乎也会触发。如果我的远程客户端是 C# 控制台,那么关闭套接字似乎会使 'A' 发生,而关闭控制台 window 似乎会使 'B' 发生。我不确定我是否理解这些场景之间的区别?
最后,问一个一般性的问题,但是这段代码或我的上述假设有什么明显的错误吗?
谢谢。
编辑:响应我使用 ObjectDisposedException 退出循环:
这就是我的 'Stop' 方法的样子(来自与上面相同的 class):
public void Stop()
{
this.tcp.Close();
}
这会导致挂起的 'ReadAsync' 异常异常。 AFAIK 没有任何其他方法可以中止它。将其更改为:
public void Stop()
{
this.tcp.Client.Shutdown(SocketShutdown.Both);
}
似乎没有对挂起的呼叫做任何事情,它只是继续等待。
当NetworkStream
returns 0时,表示socket收到了对方发来的disconnect包。这就是网络连接应该如何结束。
关闭连接的正确方法(尤其是在全双工对话中)是调用 socket.Shutdown(SocketShutdown.Send)
并给远程方一些时间来关闭他们的发送通道。这可以确保您收到任何待处理的数据,而不是关闭连接。 ObjectDisposedException
永远不应成为正常申请流程的一部分。
抛出的任何异常都表明出现了问题,我认为可以肯定地说您不能再依赖当前连接。
TL;DR
我没有发现您的代码有任何问题,但是(尤其是在全双工通信中)我会关闭发送通道并等待 0 字节数据包以防止接收 ObjectDisposedException
s默认:
使用
tcp.Shutdown(SocketShutdown.Send)
告诉对方你想断开连接您的循环可能仍会收到远程方正在发送的数据
如果一切正常,你的循环将收到一个 0 字节的数据包,表明对方正在断开连接
循环以正确的方式终止
如果您还没有收到 0 字节数据包,您可能想在一定时间后决定处理套接字