Merge pull request #1223 from ParallelogramPal/TCP-Keepalive

TCP Keepalive
This commit is contained in:
Marcel Keller
2023-11-23 14:05:01 +11:00
committed by GitHub
2 changed files with 83 additions and 0 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))

View File

@@ -120,6 +120,55 @@ void set_up_client_socket(int& mysocket,const char* hostname,int Portnum)
int one=1;
fl= setsockopt(mysocket, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));
if (fl<0) { error("set_up_socket:setsockopt"); }
/*
* The following code block is either taken directly from or derived from the solutions posted at:
* https://stackoverflow.com/questions/20188718/configuring-tcp-keep-alive-with-boostasio
* https://stackoverflow.com/questions/23669005/tcp-keepalive-protocol-not-available
*/
unsigned int timeout_milli = 10000;
#if (defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT)
int32_t timeout = timeout_milli;
fl = setsockopt(mysocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_RCVTIMEO)"); }
fl = setsockopt(mysocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_SNDTIMEO)"); }
#else
struct timeval tv;
tv.tv_sec = timeout_milli / 1000;
tv.tv_usec = (timeout_milli % 1000) * 1000;
fl = setsockopt(mysocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_RCVTIMEO)"); }
fl = setsockopt(mysocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_RCVTIMEO)"); }
int enable_keepalive = 1;
int keepalive_strobe_interval_secs = 3;
int num_keepalive_strobes = 5;
fl = setsockopt(mysocket, SOL_SOCKET, SO_KEEPALIVE,(char *)&enable_keepalive, sizeof(enable_keepalive));
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_KEEPALIVE)"); }
#ifdef TCP_KEEPIDLE
int keepalive_idle_time_secs = 1;
fl = setsockopt(mysocket, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepalive_idle_time_secs, sizeof(keepalive_idle_time_secs));
if (fl<0) { error("set_tcp_keepalive:setsockopt(IPPROTO_TCP, TCP_KEEPIDLE)"); }
#endif
fl = setsockopt(mysocket, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepalive_strobe_interval_secs, sizeof(keepalive_strobe_interval_secs));
if (fl<0) { error("set_tcp_keepalive:setsockopt(IPPROTO_TCP, TCP_KEEPINTVL)"); }
setsockopt(mysocket, IPPROTO_TCP, TCP_KEEPCNT, (char *)&num_keepalive_strobes, sizeof(num_keepalive_strobes));
if (fl<0) { error("set_tcp_keepalive:setsockopt(IPPROTO_TCP, TCP_KEEPCNT)"); }
#endif
/* End third-party code */
#ifdef __APPLE__
int flags = fcntl(mysocket, F_GETFL, 0);