Python xinetd 客户端断开连接处理

0 投票
3 回答
982 浏览
提问于 2025-04-16 00:52

这可能不是一个编码问题,也可能是xinetd守护进程的问题,我不太确定。

我有一个Python脚本,它是在运行xinetd的Linux服务器上触发的。xinetd被设置成只允许一个实例,因为我只希望一台机器能够连接到这个服务,所以它也限制了IP地址。

目前,当客户端连接到xinetd时,服务正常工作,脚本开始将输出发送到客户端机器。然而,当客户端断开连接(比如因为重启),服务器上的进程仍然在运行,这就阻止了客户端在重启完成后再次连接。

问题是:我该如何在Python中检测到客户端已经断开连接?也许我可以测试一下客户端是否不再读取标准输出(然后退出脚本),或者在xinetd中有没有更简单的方法让子进程在客户端断开时被杀掉?

(我在RHEL5 Linux上使用的是Python 2.4.3 - 需要2.4的解决方案,但3.1的解决方案也很有用。)

3 个回答

0

你似乎没有收到 SIGHUP 信号,但至少在你尝试进行任何输入输出(IO)操作时,会收到 SIGPIPE 信号。如果你的程序长时间没有进行任何 IO 操作,那么你可以启动一个线程来读取标准输入(stdin),这样一来,一旦连接断开,你就能立刻收到 SIGPIPE 信号。这种方法对我的应用程序来说足够用了,因为我只用了 xinetd 提供的管道。

我在网上看到很多人讨论客户端断开连接时是否会发送 SIGHUP 信号,所以我写了一个 inetd 的 Python 脚本来测试几个服务器(一个是 inetd,另一个是 xinetd)。你可以用这个脚本来检查信号是否被发送。它会把找到的结果记录到 /var/log/test.log 文件中。也许这对你会有帮助。

#!/usr/bin/python

import os, signal, sys

skip = ["SIGKILL", "SIG_DFL", "SIGSTOP", "SIG_IGN", "SIGCLD", "SIGCHLD"]
name_map = {}
identifiers = [i for i in dir(signal) if i.startswith("SIG") and not i in skip]

for i in identifiers:
    name_map[getattr(signal, i)] = i

def handler(num, frame):
    signame = name_map[num]
    os.system("echo handled %s >> /var/log/test.log" % signame)

if __name__ == "__main__":
    for id, name in name_map.iteritems():
        signal.signal(id, handler)

    while True:
        print sys.stdin.readline()
        sys.stdout.flush()
0

监控一下发送给你程序的信号。可能你的脚本没有对xinet发送的SIGHUP信号做出反应,监控这个信号,让它结束运行。

2

为 SIGHUP 添加一个信号处理器。这个信号是 (x)inetd 在套接字断开连接时发送的。

撰写回答