如何使用python脚本更改tcp keepalive计时器?

问题描述 投票:0回答:4

在我的 python 脚本中,我使用以下命令激活 TCP Keepalive:

x = s.setsockopt( socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

我的目标是如果 5 分钟内没有传输(*),则套接字连接关闭。我在 Windows 上工作,我的 python 脚本只接收而不向客户端程序传输任何数据。

我所知道的是,默认情况下,如果2小时内没有传输,那么只有我可以使用try和 except 关闭连接。我知道,对于 Windows,我可以通过注册表手动减少等待时间。但是有没有一种方法可以从我的脚本中修改它?

(*) 这里的“无传输”意味着“有东西悄悄地吃掉网络上的数据包”,而不是“我没有尝试发送任何东西。”

python tcp keep-alive
4个回答
73
投票

您可以使用setsockopt()在已经打开的套接字上设置TCP keepalive计时器。

import socket

def set_keepalive_linux(sock, after_idle_sec=1, interval_sec=3, max_fails=5):
    """Set TCP keepalive on an open socket.

    It activates after 1 second (after_idle_sec) of idleness,
    then sends a keepalive ping once every 3 seconds (interval_sec),
    and closes the connection after 5 failed ping (max_fails), or 15 seconds
    """
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)

def set_keepalive_osx(sock, after_idle_sec=1, interval_sec=3, max_fails=5):
    """Set TCP keepalive on an open socket.

    sends a keepalive ping once every 3 seconds (interval_sec)
    """
    # scraped from /usr/include, not exported by python's socket module
    TCP_KEEPALIVE = 0x10
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
    sock.setsockopt(socket.IPPROTO_TCP, TCP_KEEPALIVE, interval_sec)

有关 Windows 上的等效选项 请参阅 msdn 。 浏览Python源码,似乎你需要像Unix中那样用

SO_KEEPALIVE
设置
sock.setsockopt
,并且[可选?]用
SIO_KEEPALIVE_VALS
设置
sock.ioctl


15
投票

对于 Windows,在 Python 中:

这将启用套接字保持活动状态,保持活动时间为 10 秒,保持活动间隔为 3 秒。

sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, 10000, 3000))

0
投票

我结合了上面的答案,制作了一个适用于Linux、Darwin和Windows的单功能版本。

https://pypi.org/project/keepalive-socket/

pip install keepalive-socket
import socket, keepalive

# keepalive.set(socket, after_idle_sec=60, interval_sec=60, max_fails=5)

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
keepalive.set(client_socket)

0
投票

不是直接答案,但从 python 3.11 开始,选项

sock.ioctl
已在套接字包装器中删除。

https://github.com/python/cpython/pull/24538/files#diff-11e910a722981530e1b198cbd00ad6a9da3b5a16d790f668bd79ae12e16ed843L109-L111

Windows 中建议使用替代方法。有什么想法吗?

© www.soinside.com 2019 - 2024. All rights reserved.