When testing HTTP keep-alive behavior between cURL and Tomcat servers, many developers encounter situations where connections don't persist as expected. While browsers like Chrome maintain connections properly, cURL commands often show different behavior in netstat outputs.
The correct way to enable persistent connections in cURL involves multiple parameters working together:
curl --keepalive \
--keepalive-time 60 \
--max-time 300 \
http://server:8080/path/to/resource
Key flags explanation:
- --keepalive
: Enables keepalive probes
- --keepalive-time
: Sets interval between probes (seconds)
- --max-time
: Limits total operation time
To confirm keep-alive is working, use these methods:
# Server-side verification:
netstat -tulpn | grep 8080
ss -o state established '( dport = :8080 or sport = :8080 )'
# Client-side verification:
strace -e trace=network curl --keepalive http://server:8080
Several factors can prevent keep-alive from working:
# 1. HTTP/1.0 responses (add this header)
curl -H "Connection: keep-alive" --keepalive http://server:8080
# 2. Server-side timeouts (test with multiple rapid requests)
for i in {1..5}; do
curl --keepalive --keepalive-time 2 http://server:8080/resource$i
sleep 1
done
# 3. Connection closure by load balancers (add X-Forwarded-For)
curl -H "X-Forwarded-For: client_ip" --keepalive http://server:8080
For more control over connection persistence:
# Create a connection cache file
touch /tmp/curl-cache
# Use the cache for multiple requests
curl --keepalive \
--keepalive-time 30 \
--connect-timeout 5 \
--no-sessionid \
--cookie-jar /tmp/cookies \
--dump-header /tmp/headers \
--next \
http://server:8080/resource1 \
http://server:8080/resource2
Ensure your Tomcat server is properly configured:
# In server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxKeepAliveRequests="100"
keepAliveTimeout="60000" />
Remember that both client and server must support keep-alive, and intermediate proxies must not interfere with connection headers.
When debugging HTTP keep-alive behavior between cURL and Tomcat servers, there's often confusion about why connections don't persist as expected. The key insight is that cURL's default behavior differs from browsers, and proper verification requires understanding both client configuration and server-side observation.
The most effective way to enable persistent connections in modern cURL versions is through these flags:
curl --keepalive --keepalive-time 60 --keepalive-interval 60 http://server:8080/resource
For legacy systems (like your curl 7.19.5), you might need the header-based approach:
curl -H "Connection: keep-alive" -H "Keep-Alive: 300" http://server:8080/resource
To properly verify keep-alive functionality:
# On server side run before making requests:
netstat -tulnp | grep 8080
# Make multiple requests from client:
for i in {1..3}; do
curl -v --keepalive --keepalive-time 60 http://server:8080/resource
done
# Check server-side connections again
netstat -tulnp | grep 8080
Several factors can prevent keep-alive from working:
- Server configuration: Tomcat's maxKeepAliveRequests (default 100) and keepAliveTimeout
- SSL differences: Add
--ssl-reqd
for HTTPS connections - Connection pooling: Use
--next
for multiple requests on same connection
For comprehensive testing, use this bash script:
#!/bin/bash
URL="http://server:8080/resource"
TIMEOUT=60
echo "Initial connection check:"
netstat -ano | grep 8080
echo -e "\nMaking first request..."
curl -v --keepalive --keepalive-time $TIMEOUT $URL
echo -e "\nConnection after first request:"
netstat -ano | grep 8080 | grep -v TIME_WAIT
echo -e "\nMaking second request..."
curl -v --keepalive --keepalive-time $TIMEOUT $URL
echo -e "\nFinal connection state:"
netstat -ano | grep 8080
For absolute confirmation, capture traffic:
# On server:
tcpdump -i any -s 0 -w curl_capture.pcap port 8080
# Analyze in Wireshark looking for:
# - TCP connection establishment (SYN/SYN-ACK/ACK)
# - Multiple HTTP requests on same connection
# - FIN packets only after timeout