41

In my python script, I have activate TCP Keepalive using this command:

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

My goal is for socket connection to get closed, if there is no transmission(*) for 5 minutes. I am working on Windows and my python script is only receiving and not transmitting any data to client program.

What I know is, by default, if no transmission will be there for 2 hours, then only I can close the connection using try and except. I know, for windows, I can manually reduce this waiting time by going to registry. But is there is a way by which, I can modify it from my script?

(*) here "no transmission" means "something quietly eats packets on the network" rather than "I'm not trying to send anything."

2
  • clarified what "no transmission" means. Commented Nov 29, 2013 at 17:34
  • Why not just set a read timeout? Commented Jul 12, 2023 at 8:32

3 Answers 3

78

You can set the TCP keepalive timers on an already-open socket using setsockopt().

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)

For equivalent options on windows refer to msdn. Looking through the Python source, it seems you need to set SO_KEEPALIVE with sock.setsockopt similar to in Unix, and [optionally?] set SIO_KEEPALIVE_VALS with sock.ioctl.

Sign up to request clarification or add additional context in comments.

6 Comments

Note that the TCP_* constants used here are specific to Linux. For instance they are not available on OS/X
osx man tcp contains an option TCP_KEEPALIVE that accepts seconds between probes, that is equivalent to TCP_KEEPINTVL in linux. option is not exported in Python 2.7 or 3.3, but I think it's possible to use the correct integer value 0x10 as key.
@DimaTisnek TCP_KEEPINTVL looks equivalent, but how did you get that value 0x10?
Any ideas for Solaris - '_socketobject' object has no attribute 'IPPROTO_TCP', no SOL_SOCKET either
|
16

For windows, in python:

This will enable socket keep alive, with a 10 second keep alive time and a 3 second keep alive interval.

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

Comments

1

I have combined the above answers and made a single-function version for Linux, Darwin, and 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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.