我通过切断互联网连接测试了多个客户端的模拟断开连接。我发现TIdTCPServer没有释放它们的线程,它没有检测到它们断开连接。相比之下,当我手动关闭客户端时,服务器检测到断开并释放其线程。
答案 0 :(得分:3)
操作系统未及时检测到异常断开连接。丢失的套接字连接可能需要相当长的时间才能在内部超时,因此操作系统可能会使其无效。在操作系统执行此操作之前,Indy无法知道客户端连接已消失。
要考虑到这一点,您应该:
在应用层数据协议中实现超时。如果您希望客户端向您的服务器发送内容,并且在一段时间内没有这样做,请假设客户端已关闭并关闭连接。在空闲活动期间,要求客户端定期向服务器发送心跳命令以保持其连接活动。您可以使用AContext.Connection.IOHandler.CheckForDataOnSource()
方法等待数据到达,也可以使用AContext.Binding.SetSockOpt()
方法指定阻止读取的SO_RCVTIMEO
超时。
如果您无法更改数据协议,则至少可以在套接字本身上启用TCP级别保持活动。在服务器的OnConnect
事件中,您可以调用AContext.Binding.SetKeepAliveValues()
方法启用keep-alives。然后操作系统将为您处理保持活动,并在超时结束后使连接无效。
如上所述,还要确保您的服务器事件处理程序不会吞噬Indy异常(源自EIdException
)。这也可能导致服务器无法正确终止线程,如果连接丢失并且Indy引发了关于它的异常,但是您不允许服务器处理它。如果需要捕获异常(用于记录等),请确保重新引发任何EIdException
派生的异常并让服务器处理它。