8

我有一个 TcpClient 对象,它使用其底层 NetworkStream.Write() 向服务器发送一些数据。因此,我有:

TcpClient server = new TcpClient(serverName, 50001);

/* ... */

NetworkStream stream = server.GetStream();

现在,当按下按钮时,连接应该关闭。关闭连接的正确方法是什么?MSDN 文档说关闭 TcpClient(使用 .Close())实际上并没有关闭套接字,只关闭了 TcpClient 资源(这至少是我理解文档的方式)。

那么,执行下一个代码会正确关闭连接吗?

stream.Close();
server.Close();

这是否足够,或者我应该首先(以某种方式)检查流(或服务器)是否可以关闭(以防连接半开或其他情况)......

更重要的是,NetworkStream.Close()MSDN 文档声明它释放资源(甚至是套接字),所以也许关闭流就足够了,因为我在那之后阻止使用 TcpClient。

什么是正确的方法?

4

3 回答 3

6

正如文档所说:

调用此方法最终会导致关联的 Socket 关闭,并且还会关闭关联的用于发送和接收数据的 NetworkStream(如果已创建)。

所以server.Close();就足够了。

不过,首先关闭 NetworkStream 永远不会受到伤害。

顺便说一句,如果您碰巧仅在一种方法中使用 TcpClient,请将其包装在一个using( )语句中,以便您确定Dispose()(等效于Close())在其上调用,即使抛出异常等。

于 2009-11-20T09:20:23.807 回答
3

我会将 TCP 连接与套接字相关联。

一般流程是这样的: 1. 发送完数据 2. 调用 Socket.Shutdown 并带上 SocketShutdown.Send 参数 3. 在 Receive 上循环直到返回 0 或异常失败 4. 调用 Close()

这是伪代码中的一个小示例,与 C# 非常相似:)

void CloseConnection(Socket socket)
{
   socket.Send(/*last data of the connection*/);
   socket.Shutdown(SocketShutdown.Send);

   try
   {
      int read = 0;
      while( (read = socket.Receive(/*application data buffers*/)) > 0 )
      {}
   }
   catch
   {
      //ignore
   }
   socket.Close();
}

如果跳过第一步和第三步 - 可能会发生数据丢失。

取自如何关闭 TCP 套接字

于 2009-11-20T09:33:13.220 回答
0

您正确地关闭了流然后关闭了服务器。正如文档所述,这应该会导致所有套接字随着时间的推移成功关闭。然而,随着时间的推移,一些令人头疼的错误教会了我重要的一课:

别忘了冲洗!

stream.Flush();
stream.Close();
server.Close();

您经常会丢失一些您认为可能已经发送的数据。这也有助于确保在您关闭流时该流应该是空的且处于非活动状态。

于 2009-11-20T09:24:17.793 回答