C# 关闭 TCP 连接的正确方法是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1769271/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:39:30  来源:igfitidea点击:

What is the correct way to close a TCP connection

c#tcpnetworkstream

提问by Kornelije Petak

I have a TcpClient object which sends some data to server, using its underlying NetworkStream.Write(). Therefor, I have:

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

TcpClient server = new TcpClient(serverName, 50001);

/* ... */

NetworkStream stream = server.GetStream();

Now, when a button is pressed, the connection should close. What is the right way to close the connection? The MSDN docs say that closing the TcpClient (with .Close()) does not in fact close the socket, only the TcpClient resources (that's at least the way I understood the docs).

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

So, would doing the next code correctly close the connection?

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

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

Is this enough, or should I first check (somehow) if the stream (or server) can be closed (in case the connection is half-open or something)...

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

Even more, NetworkStream.Close()MSDN docs states that it releases resources (even sockets), so maybe closing the stream would be enough, taken that I prevent using the TcpClient after that point.

更重要的是,NetworkStream.Close()MSDN 文档指出它会释放资源(甚至是套接字),因此可能关闭流就足够了,因为在那之后我会阻止使用 TcpClient。

What is the right approach?

什么是正确的方法?

采纳答案by Joren

As the docssay:

正如文档所说:

Calling this method will eventually result in the close of the associated Socket and will also close the associated NetworkStream that is used to send and receive data if one was created.

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

So server.Close();will be enough.

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

Closing the NetworkStream first will never hurt though.

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

By the way, if you happen to be using the TcpClient only in one method, wrap it in a using( )statement so that you're sure Dispose()(equivalent to Close()) is called on it, even if exceptions are thrown etc.

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

回答by Smallgods

You're right in closing the stream then the server. This should result in all sockets being closed successfully over time, as the documentation states. However, several head scratching bugs have taught me the important lesson over time:

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

Don't forget to flush!

别忘了冲洗!

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

You will often lose some data you thought you might have sent otherwise. This also helps ensure that the stream should be empty and inactive when you close it.

您经常会丢失一些您认为可能以其他方式发送的数据。这也有助于确保流在您关闭时应该是空的和不活动的。

回答by Vadym Stetsiak

I will associate a TCP connection with a socket.

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

Generally, the procedure is like this: 1. Finish sending data 2. Call Socket.Shutdown with SocketShutdown.Send parameter 3. Loop on Receive until it returns 0 or fails with an exception 4. Call Close()

一般的过程是这样的: 1. 完成发送数据 2. 使用 SocketShutdown.Send 参数调用 Socket.Shutdown 3. 循环接收直到返回 0 或失败并出现异常 4. 调用 Close()

Here's a small sample in pseudo code that is very similar to C# :)

这是伪代码中的一个小示例,与 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();
}

If first and third steps are skipped - data loss can happen.

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

Taken from How to close TCP socket

取自如何关闭 TCP 套接字