TCP连接中客户端与服务器缓冲区大小不同的行为探究
TCP连接两端缓冲区大小不同时的行为分析
嘿,这个问题问到了TCP协议的核心特性——咱们先直接给结论:完全不会丢失数据,服务器设置的BUFFER_SIZE=5只是单次recv()调用能读取的最大字节数,不是只能接收5字节。TCP是面向字节流的协议,它会保证客户端发送的所有数据完整、有序地到达服务器的接收缓冲区,服务器只需要通过多次调用recv()就能把所有数据读出来。
咱们来拆解这段代码的完整运行逻辑:
客户端代码逻辑
import socket,sys TCP_IP = sys.argv[1] TCP_PORT = int(sys.argv[2]) BUFFER_SIZE = 1024 MESSAGE = "World! Hello, World!" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((TCP_IP, TCP_PORT)) s.send(MESSAGE) data = s.recv(BUFFER_SIZE) s.close() print "received data:", data
- 客户端首先和指定IP、端口的服务器建立TCP连接
- 发送的
MESSAGE是长度为18字节的字节串(Python2中字符串默认是字节流) - 调用
send(MESSAGE)把这18字节全部写入TCP发送缓冲区,由TCP协议负责可靠传输到服务器 - 等待服务器返回响应,单次
recv(1024)会把服务器发回的所有大写字符串(同样18字节)一次性读取 - 最后关闭连接并打印收到的数据
服务器代码逻辑
import socket,sys TCP_IP = '0.0.0.0' TCP_PORT = int(sys.argv[1]) BUFFER_SIZE = 5 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((TCP_IP, TCP_PORT)) s.listen(1) while True: conn, addr = s.accept() print 'New connection from:', addr while True: data = conn.recv(BUFFER_SIZE) if not data: break print "received:", data conn.send(data.upper()) conn.close()
- 服务器绑定所有网卡的指定端口,开始监听连接请求
- 当客户端连接进来后,进入内层循环处理数据:
- 第一次
recv(5):从接收缓冲区读取前5字节,得到"World",转成大写"WORLD"发回客户端 - 第二次
recv(5):读取接下来的5字节,得到"! Hel",转成大写"! HEL"发回 - 第三次
recv(5):读取接下来的5字节,得到"lo, W",转成大写"LO, W"发回 - 第四次
recv(5):读取剩余的3字节(因为总长度18,前三次读了15),得到"orld!",转成大写"ORLD!"发回
- 第一次
- 当客户端关闭连接后,
recv()会返回空字节串,服务器退出内层循环,关闭当前连接,继续等待新的连接
关键知识点澄清
- TCP是面向字节流的:不存在“数据包”的概念,发送方发送的字节会被TCP拼成连续的字节流传输,接收方需要自己处理字节的拆分/拼接,只要接收方循环调用
recv()直到返回空,就能拿到所有数据 - recv(n)的含义:表示从接收缓冲区中最多读取n字节,如果缓冲区中剩余字节数少于n,就返回当前所有可用字节;如果缓冲区为空,就阻塞等待(直到有数据到达或连接关闭)
- 你提到的
1024÷5是误解:客户端的BUFFER_SIZE=1024是它自己单次recv()的最大读取量,而客户端实际发送的是18字节,不是1024字节,所以服务器只需要4次recv(5)就能读完所有数据
内容的提问来源于stack exchange,提问作者Dima Ciun
相关产品推荐
相关产品推荐

