When working with TCP sockets on Linux, the send and receive buffer sizes significantly impact network performance. These buffers temporarily store data before transmission (send buffer) or after reception (receive buffer). The kernel dynamically adjusts these values based on various factors, but applications can override them using socket options.
Several methods exist to inspect TCP buffer sizes for active sockets:
// Using ss command (preferred)
ss -ntmp
// Sample output:
// ESTAB 0 0 192.168.1.100:54322 192.168.1.200:443
// skmem:(r1024,rb87380,t0,tb1310720,f0,w0,o0,bl0)
// Here rb87380 shows receive buffer size, tb1310720 shows send buffer size
For more precise control, you can check buffer sizes programmatically:
#include <sys/socket.h>
#include <stdio.h>
void check_buffer_sizes(int sockfd) {
int sndbuf, rcvbuf;
socklen_t len = sizeof(sndbuf);
getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len);
getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len);
printf("Send buffer: %d, Receive buffer: %d\n", sndbuf, rcvbuf);
}
Kernel maintains default and maximum buffer sizes that can be checked via:
// Default values
cat /proc/sys/net/ipv4/tcp_rmem // Min Default Max receive
cat /proc/sys/net/ipv4/tcp_wmem // Min Default Max send
// Current maximums
cat /proc/sys/net/core/rmem_max
cat /proc/sys/net/core/wmem_max
When diagnosing buffer size issues:
- Remember that the kernel doubles the requested SO_SNDBUF/SO_RCVBUF value
- Actual buffer usage might be lower due to memory pressure
- Use netstat -s to check for buffer-related errors
For detailed per-socket buffer analysis, consider using systemtap:
probe kernel.function("tcp_recvmsg") {
printf("PID %d socket %p rcvbuf: %d\n", pid(), $sk, $sk->sk_rcvbuf)
}
Linux provides several ways to examine TCP socket buffer configurations. Here are the most effective methods:
// Method 1: Using ss command
ss -ntmp
// Sample output:
ESTAB 0 0 192.168.1.100:443 203.0.113.45:54321
skmem:(r512,r512,t0,tb46080,f0,w0,o0,bl0) // r512=receive buffer, tb46080=send buffer
The skmem
field shows memory usage with these components:
r
: receive buffer sizetb
: transmit buffer size
For precise control, use the getsockopt() system call:
#include <sys/socket.h>
#include <stdio.h>
void check_buffer_sizes(int sockfd) {
int sndbuf, rcvbuf;
socklen_t len = sizeof(sndbuf);
getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len);
getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len);
printf("Send buffer: %d\nReceive buffer: %d\n", sndbuf, rcvbuf);
}
The kernel automatically adjusts the actual buffer sizes based on:
net.ipv4.tcp_wmem
(default: 4096 16384 4194304)net.ipv4.tcp_rmem
(default: 4096 87380 4194304)
Check current system-wide settings:
sysctl net.ipv4.tcp_wmem net.ipv4.tcp_rmem
When you set SO_SNDBUF/SO_RCVBUF, the kernel doubles the value (for overhead) and clamps it within system limits:
int new_size = 102400; // 100KB
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &new_size, sizeof(new_size));
// Actual size will be min(max(2*new_size, tcp_wmem[0]), tcp_wmem[2])
Modern Linux kernels dynamically adjust buffers based on:
cat /proc/sys/net/ipv4/tcp_moderate_rcvbuf // Typically set to 1 (enabled)
For real-time monitoring of buffer usage per connection:
watch -n 1 'cat /proc/net/sockstat | grep "TCP: inuse"'