如何检测 Indy TCP 客户端中的连接失败

How to detect a connection failure in Indy TCP Client

我在 C++Builder 11 Alexandria 中使用 Indy TIdTCPClientTIdTCPServer 创建了客户端和服务器。

我可以启动服务器并将客户端正确连接到它,但是如果我将服务器 MaxConnections 设置为值 N 并且我尝试使用 [=16= 连接到它] 客户端,显然连接没有失败。

例如:我在服务器中设置 MaxConnections=1,第一个客户端连接到它并且引发服务器 OnConnect 事件,而在客户端 OnStatus 事件中我得到两个留言:

message 1: Connecting to 10.0.0.16.
message 2: Connected.

我尝试连接第二个客户端:未引发服务器 OnConnect 事件(这是我所期望的)但是在客户端 OnStatus 事件中我收到了相同的两条消息(并且这不是我所期望的):

message 1: Connecting to 10.0.0.16.
message 2: Connected.

然后,第一个客户端可以与服务器交换数据,而第二个客户端不能(这似乎是正确的)。

我不明白为什么第二个客户端连接没有显式失败,我是不是做错了什么?

不同的 TCP 堆栈表现出不同的行为。您的描述与 TCP 堆栈一致,该堆栈简单地忽略 SYN 到已达到挂起 and/or 已接受连接的最大配置限制的套接字:SYN 数据包只是丢弃在地板上并且未被确认。

TCP 的本质是它应该处理网络丢失。发件人不会立即退出,但会在一段时间内继续尝试连接。这部分与所有TCP实现一致。

如果您希望您的客户端在某个设定的时间段内未建立的连接快速失败,您需要自己实施手动超时。

你没有做错任何事。这是 TIdTCPServer 的正常行为。

OS级别没有跨平台socketAPI1来限制active[=38]的数量=]/accepted TCP 服务器套接字上的连接,仅用于限制服务器积压中挂起的连接数。该限制由 TIdTCPServer::ListenQueue 属性 处理,默认情况下为 15(但这更像是一个建议而不是硬限制,如果需要,底层套接字堆栈可以覆盖它到).

因此,TIdTCPServer::MaxConnections 属性 的实现方式是简单地接受积压中任何尝试连接的客户端,然后 立即断开连接 该客户端如果超过 MaxConnections 限制。

因此,如果您尝试将比 MaxConnections 允许的更多的客户端连接到 TIdTCPServer,这些额外的客户端将不会看到任何连接失败(除非积压填满),但服务器会不要为他们触发 OnConnect 事件。从客户端的角度来看,他们实际上确实连接成功,他们被服务器底层套接字堆栈完全接受(TCP 3way 握手完成)。然而,他们根本不会处理断开连接,直到他们尝试与服务器实际通信,然后他们将检测到断开连接,通常以 EIdConnClosedGracefully 异常的形式(但不能保证)。

1:仅在 Windows 上,有一个 WSAAccept() 函数,它有一个回调函数,可以在挂起的连接离开积压队列之前拒绝它们。但是 Indy 目前没有使用这个回调。