C语言 如何监视/关闭网络程序中挂起的网络会话



我正在编写类似以下内容(直径协议)的东西,我需要实现一个计时器来监视会话挂起状态并在它们超过某个阈值时终止它们,最好的方法是什么?

请注意,我正在寻找算法。

Credit-Control Application Related Parameters
Tx timer
When real-time credit-control is required, the credit-control
client contacts the credit-control server before and while the
service is provided to an end user.  Due to the real-time nature
of the application, the communication delays SHOULD be minimized;
e.g., to avoid an overly long service setup time experienced by
the end user.  The Tx timer is introduced to control the waiting
time in the client in the Pending state.  When the Tx timer
elapses, the credit-control client takes an action to the end user
according to the value of the Credit-Control-Failure-Handling AVP
or Direct-Debiting-Failure-Handling AVP.  The recommended value is
10 seconds.

你不一定需要计时器。

当您的应用程序接受新连接时,例如 accept(),您可以使用例如 clock_gettime()(特别是使用 CLOCK_BOOTTIME 时钟,这需要 2.6.39 或更高版本的内核)。

在处理过程中,尤其是在发送任何响应之前,代码必须检查连接(时间戳)是否还不太旧。

虽然实现起来非常简单且非常精确,但clock_gettime()调用并不是特别快。也就是说,它本身不是一个缓慢的调用 - 没有更快的方法来获取当前时间--,只是根据当前时间检查时间戳确实需要每次clock_gettime()调用,从而导致可能生成大量此类调用。

如果性能比精度更重要,则可以使用定时器中断。计时器中断发生在指定的时间间隔之后;它们可能会延迟。换句话说,虽然计时器中断不应在间隔过之前触发,但允许它们在之后的任何时间触发。因此,超时并不像上面那么严格。

计时器过后,信号处理程序将设置特定于连接/超时的标志。您的函数不会检查时间戳,而是验证该标志是否尚未设置。

由于 Linux 中的计时器是有限的资源(不稀缺,只是可能限制为少于可能的同时客户端连接数)——限制大约是 getrlimit(RLIMIT_SIGPENDING) ,在我的机器上大约有四万个 --, 我建议不要使用 timer_create()timerfd_create() 为每个连接创建一个单独的计时器。

相反,我会使用实时信号(例如SIGRTMIN+1)和(高优先级)线程在sigwaitinfo()上循环,信号在所有其他线程中被阻止,维护下一个超时事件。当sigwaitinfo()调用返回时,它还会注册新的超时事件;这样,任何线程都可以通过创建一个合适的结构,将其添加到链或数组中,然后发出实时信号来添加新的超时事件。siginfo_t结构(定义见sigaction())告诉信号是由定时器产生的还是通过例如 sigqueue() .

通常,使用计时器中断通常是首选,因为它比重复比较时间戳与当前时间的开销更少,并且大多数应用程序不在乎超时是否有点晚(只要永远不会太早)。特别是,一个客户端的十秒超时可能是 10.0 秒,另一个客户端的超时可能是 10.1 秒。

很难说超时是否应该在您的情况下准确无误。您引用的规范似乎强调最小延迟,而具有确切的超时(甚至所有客户端的相同超时)似乎并不那么重要。我个人的观点倾向于使用计时器中断。

无论您选择哪种方法进行超时处理,我都建议您从一开始就将超时处理设计到逻辑中。在这两种情况下,代码都需要定期检查连接是否已超时;一种方法只是将当前时间与原始时间戳进行比较,另一种方法是标志。只要设计超时签入,就不太可能错过任何需要检查超时条件以实现稳健可靠操作的地方。

希望这有帮助。

最新更新