C# - 如何关闭NetworkStream,调用stream.Close还是socket.Shutdown?

9

我想知道如何最好地处理使用Socket对象和NetworkStream对象的类?该类具有一个NetworkStream实例和一个Socket实例,用于创建NetworkStream。

this.socket = new Socket(
                           AddressFamily.InterNetwork,
                           SocketType.Stream,
                           ProtocolType.Tcp)
                        {
                            ReceiveBufferSize = 65536,
                            SendBufferSize = 150
                        };

this.socket.Connect(
                        new IPEndPoint(                                                                   
                              IPAddress.Parse(
                                          Properties.Settings.Default.MpsServer2),
                                          Properties.Settings.Default.MpsPort2));

this.stream = new NetworkStream(
                         this.socket, true);

在我的Dispose方法中,我应该这样做吗?
this.stream.Close();
this.socket.Shutdown(SocketShutdown.Both);
this.socket.Close();

这些都是必要的,还是过度了?
3个回答

2
Socket没有处理相关的NetworkStream。我还启动了反编译工具进行确认。(这是一个分析.NET dlls和.NET库的工具,非常好用。在免费版本结束之前,您有一个月的时间去下载它)。
然而,根据MSDN文档和反编译器的说法,只有当流拥有套接字时,它才会关闭套接字。你可以将其设置为重载构造函数的第二个参数。
无论如何,您都必须调用Shutdown,因为它会清除数据。如果不这样做,您可能会丢失数据。

我会将这个标记为正确答案,因为它有最多的文档支持。我想知道流的Dispose方法是否可以完成这项工作,但似乎没有太多关于它到底会做什么的信息。 - Nick Ramirez

1

SocketStream都实现了IDisposable接口,因此您可以在每个对象上调用.Dispose()方法。Dispose方法应该处理关闭和其他必要的处理操作。

this.stream.Dispose(); 
this.socket.Dispose(); 

例如,这是从流类中反汇编的Dispose方法:
public void Dispose()
{
    this.Close();
}

你不能在套接字上调用 Dispose 方法,只能使用 Close 方法。 - Marlon
1
Socket的IDisposable实现是显式的,这意味着它没有"public" Dispose方法,您必须将Socket转换为IDisposable才能调用Dispose,例如((IDisposable)socket).Dispose()... - haze4real
1
使用 (var socket = new Socket()) {..} 将调用 Dispose()。 - Hiep

1
根据MSDN文档,调用stream.Close() "关闭当前流并释放与当前流相关联的任何资源(例如套接字和文件句柄)",这告诉我stream.Close()也会处理套接字。不过你仍然需要调用socket.Shutdown()。无论如何,在我看来,最安全的方法是使用"using",它可以让你更加安心 :)
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                        {
                            ReceiveBufferSize = 65536,
                            SendBufferSize = 150
                        };) {
  socket.Connect(
    new IPEndPoint(
      IPAddress.Parse(
        Properties.Settings.Default.MpsServer2), Properties.Settings.Default.MpsPort2));

  using (var stream = new NetworkStream(socket, true) {
    // do something with the stream here
  }

  socket.Shutdown(SocketShutdown.Both);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接