Add Application-level Keepalive

This commit is contained in:
Parker Diamond
2023-11-14 13:59:21 -05:00
parent d4c96c61bd
commit 7acbfc1bde
3 changed files with 83 additions and 1 deletions

View File

@@ -1,7 +1,34 @@
import platform
import socket, ssl
import struct
import time
# The following function is either taken directly or derived from:
# https://stackoverflow.com/questions/12248132/how-to-change-tcp-keepalive-timer-using-python-script
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)
# The following function is either taken directly or derived from:
# https://stackoverflow.com/questions/12248132/how-to-change-tcp-keepalive-timer-using-python-script
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)
class Client:
def __init__(self, hostnames, port_base, my_client_id):
ctx = ssl.SSLContext()
@@ -22,6 +49,13 @@ class Client:
time.sleep(1)
else:
raise
if platform.system() == "Linux":
set_keepalive_linux(plain_socket)
elif platform.system() == "Darwin":
set_keepalive_osx(plain_socket)
set_keepalive_linux(plain_socket)
octetStream(b'%d' % my_client_id).Send(plain_socket)
self.sockets.append(ctx.wrap_socket(plain_socket,
server_hostname='P%d' % i))