You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

socket.send未发送全部数据的场景及复现方法问询

如何复现socket.send()不发送全部数据的场景

要复现send()仅发送部分数据的情况,核心是让发送端的TCP发送缓冲区没有足够空间一次性容纳所有待发送数据,以下是几种可靠的实现方式:

方法1:使用非阻塞Socket发送超缓冲区数据

将Socket设置为非阻塞模式后,当待发送数据超过当前发送缓冲区剩余容量时,send()会立即返回已发送的字节数(小于总长度),不会阻塞等待。

示例代码:

import socket

# 创建TCP Socket并设置为非阻塞模式
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 8080))
s.setblocking(False)

# 准备远大于默认缓冲区容量的数据(1MB)
large_data = b"X" * 1024 * 1024

try:
    sent_bytes = s.send(large_data)
    print(f"实际发送字节数: {sent_bytes}, 总数据长度: {len(large_data)}")
    if sent_bytes < len(large_data):
        print("成功复现部分发送场景")
except BlockingIOError:
    print("缓冲区已满,无数据可发送")

方法2:控制接收端的TCP窗口大小

通过让接收端的接收缓冲区填满,迫使TCP接收窗口缩小,发送端的send()会因对方无法接收全部数据而返回部分发送结果。

接收端代码(故意不读取数据):

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 8080))
server.listen(1)
conn, addr = server.accept()
# 不调用recv(),让接收缓冲区被填满
input("按任意键开始读取数据...")
conn.recv(1024 * 1024)

发送端代码:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 8080))

# 发送512KB数据
large_data = b"X" * 1024 * 512
sent_bytes = s.send(large_data)
print(f"实际发送字节数: {sent_bytes}, 总数据长度: {len(large_data)}")

方法3:手动缩小发送缓冲区容量

通过SO_SNDBUF选项将发送缓冲区设置为很小的值,再发送超过该容量的数据,非阻塞模式下会直接返回部分发送结果。

示例代码:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 8080))
# 将发送缓冲区设置为1KB
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024)
s.setblocking(False)

# 发送4KB数据,远大于缓冲区容量
data = b"X" * 4096
sent_bytes = s.send(data)
print(f"实际发送字节数: {sent_bytes}, 总数据长度: {len(data)}")

内容的提问来源于stack exchange,提问作者NiklasMM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 17:20:27