TCP Buffer

看tcp socket buffer size:

[root@VM_137_43_centos ~]# cat /proc/sys/net/ipv4/tcp_rmem
4096    87380   6291456
[root@VM_137_43_centos ~]# cat /proc/sys/net/ipv4/tcp_wmem
4096    16384   4194304       

三个数字分别表示最小、默认、最大的内存限制。

简单验证下tcp write buffer到底有多大。
客户端:

import socket
import sys
import os
import errno
import time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                 
s.connect((sys.argv[1] , int(sys.argv[2])))
s.setblocking(0)
buf = "*" * 1024
cnt = 0
while True:
    try:
        n = s.send(buf)
        cnt += n
        sys.stdout.write("\r send %s bytes, total:%s" % (n, cnt))
        sys.stdout.flush()
        time.sleep(0.2)
    except IOError as err:
        if err.errno == errno.EWOULDBLOCK:
            print
            print("write buffer is full, send %s bytes total" % cnt)
            a = raw_input("enter q to exit:")
            if a == 'q':
                break
    except:
        raise
s.close()

服务端:

import socket
import sys

HOST = sys.argv[1]  
PORT = int(sys.argv[2])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(128)
while 1:
    conn, addr = s.accept()
    print('Connected by', addr)
    while True:
        data = conn.recv(1024)
        if not data:
            conn.close()
            break
        print data 

为了让客户端buffer写满,服务端需要在s.accept()后打上断点,不读客户端数据。

服务端可以用python -m pdb test_server.py 127.0.0.1 1234运行。
客户端python test_client.py 127.0.0.1 1234

客户端观察到:

write buffer is full, send 696704 bytes total

说明发送了696704字节后数据,调用write开始阻塞,buffer写满了。

wireshark抓包:

img 服务端最后的ACK是322561,说明客户端的写buffer里面至少还有696704-322560=374144字节的数据,同理也可以知道服务端的读buffer至少有322560个字节已经ACK过的数据。

可以用setsockopt函数去设置每个连接的读写缓冲(SO_RCVBUF and SO_SNDBUF)。

但我测试发现SO_RCVBUF的大小并不严格等于TCP ACK过的数据大小(Win=0且未去读socket数据),只能说数量级比较接近。 img 图片中当win=0时ACK为11761,但是我设置的RCVBUF为8192,实际缓存数据是要稍大于RCVBUF的。

参考: