且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 C# 中检查(TCP)套接字是否已(断开)连接?

更新时间:2023-11-28 10:03:04

一个 socket 的死亡会以多种方式改变它的行为,所以这些方法都是有效的 :)

Death of a socket changes its behavior in several ways, so these methods are both valid :)

使用这两种方法,您实际上可以检查断开连接后发生变化的套接字行为的那些部分.

With both methods you actually check those parts of the socket's behavior that change after disconnection.

我不太明白他关于调用 Receive() 以确保远程端点实际上已收到我发送的所有数据的说法.(套接字会阻塞接收直到发送缓冲区为空吗?)

I don't really understand his statement about calling Receive() to make sure that the remote endpoint has actually received all the data I sent. (Do sockets block receiving until the sending buffer is empty?)

TCP 是可靠的协议,这意味着您发送的每个数据包都必须得到确认.确认意味着发送带有 ACK 位设置的数据包.这些数据包可能包含也可能不包含附加(有效载荷)数据.

TCP is reliable protocol, that means that every packet you send must be acknowledged. Acknowledgement implies sending the packets with ACK bit set. These packets may or may not contain additional (payload) data.

当套接字连接时,Receive() 将阻塞,直到套接字接收到具有非空负载的数据包.但是当socket断开时,Receive()会在最后一个ACK包到达时返回.

When the socket is connected, Receive() will block until the socket receives a packet with non-empty payload. But when the socket is disconnected, Receive() will return as soon as the last ACK packet arrives.

调用 Receive() 可确保您接收来自远程端点的最后一个 ACK 数据包,或者发生断开连接超时,您将能够在这个套接字上接收什么.

Calling Receive() ensures that you either receive that last ACK packet from your remote endpoint or a disconnect timeout occurs and you will be able to receive nothing more on this socket.

同一页面上的示例显示了如何执行此操作.(我想知道为什么它会分配一个 1 字节的数组,即使它以 0 长度调用 Send?)但是 Ian Griffiths 的一篇文章说我应该从套接字读取,而不是通过它发送.

The example on the same page shows how to do it. (I wonder why does it allocate a 1-byte array, even though it calls Send with 0 length?) But a post by Ian Griffiths says that I should read from the socket, not send through it.

send() 发送到套接字时,您实际上尝试将一些数据附加到套接字队列的末尾.缓冲区中是否有剩余空间,然后您的 Send() 立即返回,如果没有,Send() 会阻塞直到有位置.

When send()ing to a socket, you actually try to append some data to the end of the socket queue. Is there is some place left in the buffer, then your Send() returns instantly, if not, the Send() blocks until there is some place.

当套接字处于断开连接状态时,TCP/IP 堆栈会阻止对缓冲区的所有进一步操作,这就是 Send() 返回错误的原因.

When the socket is in disconnected state, TCP/IP stack prevents all further operations with the buffer, that's why Send() returns an error.

Send() 实现了一个基本的指针检查,这意味着当一个 NULL 指针被传递给它时它会失败.您可能会将任何非空常量作为指针传递,但***分配 1 个字节而不是将常量组合起来——以防万一.

Send() implements a basic pointer check, this means it fails when a NULL pointer is passed to it. You may probably pass any non-null constant as a pointer, but you better allocate 1 byte instead of making the constant up — just in case.

您可以使用任何您喜欢的方法,因为它们都不消耗资源.只要是用于socket连接检查的,都是一样的.

You may use any method you like, as none of them is resource consuming. As long as they are used for socket connection checking, they are identical.

至于我,我更喜欢 Receive(),因为这是您通常在一个循环中运行并等待的内容.你从 Receive() 得到一个非零值,你处理数据;你得到一个零,你处理断开连接.

As for me, I would prefer Receive(), as this is what you normally run in a cycle and wait for. You get a non-zero from Receive(), you process data; you get a zero, you process disconnection.