I am running below client server program which are communicating via local loopack address and try to capture the tcpdump output. Though program has specifically set for sending keep alive msg periodically, but I do not see it in tcpdump. Any idea why?
server.py
import socket
def start_server():
server_host = '127.0.0.1'
server_port = 12345
backlog = 5 # Maximum number of queued connections
# Create a TCP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Enable TCP keep-alive on the server socket
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Set TCP keep-alive options (optional, you can adjust these as needed)
server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
# Bind the socket to the server address and port
server_socket.bind((server_host, server_port))
# Listen for incoming connections
server_socket.listen(backlog)
print(f"Server is listening on {server_host}:{server_port}")
while True:
print("Waiting for a connection...")
client_socket, client_address = server_socket.accept()
print(f"Accepted connection from {client_address}")
while True:
data = client_socket.recv(1024)
if not data:
break
print(f"Received: {data.decode('utf-8')}")
client_socket.send(data) # Echo the data back to the client
client_socket.close()
print(f"Connection with {client_address} closed")
if __name__ == "__main__":
start_server()
client.py
import socket
import time
def start_client():
server_host = '127.0.0.1'
server_port = 12345
# Create a TCP socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Enable TCP keep-alive on the client socket
client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# Set TCP keep-alive options (optional, you can adjust these as needed)
client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
try:
# Connect to the server
client_socket.connect((server_host, server_port))
print(f"Connected to {server_host}:{server_port}")
while True:
message = input("Enter a message to send (or 'exit' to quit): ")
if message == 'exit':
break
client_socket.send(message.encode('utf-8'))
response = client_socket.recv(1024)
print(f"Server response: {response.decode('utf-8')}")
finally:
client_socket.close()
print("Connection closed")
if __name__ == "__main__":
start_client()
I kept socket channel open for 5 mins without any activity also but did not see any keep alive pkt however there are some pkt transfer still happening periodically but don't seem a keep alive
/home/ravi> tcpdump -i lo -n -vvv 'port 12345'
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
....
....
03:41:48.073820 IP (tos 0x0, ttl 64, id 50758, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.12345 > 127.0.0.1.49088: Flags [.], cksum 0xfe28 (incorrect -> 0x38ba), seq 4, ack 4, win 512, options [nop,nop,TS val 2055232093 ecr 2055170654], length 0
03:41:48.073832 IP (tos 0x0, ttl 64, id 27799, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.49088 > 127.0.0.1.12345: Flags [.], cksum 0xfe28 (incorrect -> 0x38ba), seq 3, ack 5, win 512, options [nop,nop,TS val 2055232093 ecr 2055170654], length 0
03:41:48.073868 IP (tos 0x0, ttl 64, id 27800, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.49088 > 127.0.0.1.12345: Flags [.], cksum 0xfe28 (incorrect -> 0x38b9), seq 4, ack 5, win 512, options [nop,nop,TS val 2055232093 ecr 2055170654], length 0
03:41:48.073876 IP (tos 0x0, ttl 64, id 50759, offset 0, flags [DF], proto TCP (6), length 52)
127.0.0.1.12345 > 127.0.0.1.49088: Flags [.], cksum 0xfe28 (incorrect -> 0x38b9), seq 5, ack 4, win 512, options [nop,nop,TS val 2055232093 ecr 2055170654], length 0
....
....
What you see are actually two keep-alive probes with their matching reply - only you did not realize this since tcpdump does not explicitly say so. To reduce the output from tcpdump to the essential parts:
1 127.0.0.1.12345 > 127.0.0.1.49088: ... seq 4, ack 4, ... length 0
3 127.0.0.1.49088 > 127.0.0.1.12345: ... seq 4, ack 5, ... length 0
In packet #1 is the keep-alive probe from the (presumably) server. The sequence number (seq=4) is one less than the current one and the payload is empty, so this is a keep-alive probe. The peer (client) answers in packet 3 with an ack which contains the real sequence number seen from the server (ack=5).
2 127.0.0.1.49088 > 127.0.0.1.12345: ... seq 3, ack 5, ... length 0
4 127.0.0.1.12345 > 127.0.0.1.49088: ... seq 5, ack 4, ... length 0
In packet #2 is the keep-alive probe from the (presumably) client. Again, sequence number (seq=3) is one less and the payload empty. The reply from the peer (server) acks as expected the real sequence number seen (ack=4).
If you would view the same packet capture in Wireshark it would likely explicitly highlight the TCP keep-alive. tcpdump does not do this and interpretation of the packets is left to the one using the tool.