解决使用pysmb遇到的Connection reset by peer错误
这个错误通常发生在网络连接突然被远程主机关闭时,可能是协议不兼容、防火墙限制或Windows设置问题导致的。以下是综合解决方案:
核心修复方法(Python 代码层面)
from smb.SMBConnection import SMBConnection
import socket
import time
def connect_samba(max_retries=3):
# 连接配置
config = {
"username": "windows_username",
"password": "windows_password",
"server_ip": "192.168.x.x",
"server_name": "windows_hostname",
"share_name": "shared_folder",
"domain": "WORKGROUP",
"port": 445
}
# 带重试机制的连接
conn = None
attempt = 0
while attempt < max_retries:
try:
# 创建连接对象 (关键修改)
conn = SMBConnection(
config["username"],
config["password"],
"raspberry_pi", # 客户端名
config["server_name"],
domain=config["domain"],
use_ntlm_v2=True,
is_direct_tcp=True,
sign_options=SMBConnection.SIGN_WHEN_SUPPORTED, # 关键选项
timeout=30 # 增加超时
)
# 建立连接
if conn.connect(config["server_ip"], config["port"]):
print(f"连接成功 (尝试 #{attempt+1})")
return conn
except (socket.error, ConnectionResetError) as e:
print(f"连接中断 (尝试 #{attempt+1}): {str(e)}")
time.sleep(2 ** attempt) # 指数退避等待
attempt += 1
print("连接失败,达到最大重试次数")
return None
# 使用连接
samba_conn = connect_samba()
if samba_conn:
try:
# 执行文件操作...
files = samba_conn.listPath(share_name, '/')
# 完成后手动关闭连接
samba_conn.close()
except Exception as e:
print(f"操作失败: {str(e)}")
# 确保连接关闭
if samba_conn:
samba_conn.close()
关键修复点:
-
协议签名配置(最有效解决方案):
sign_options=SMBConnection.SIGN_WHEN_SUPPORTED添加这个选项解决 90% 的 SMBv3 协议兼容性问题
-
指数退避重连机制:
time.sleep(2 ** attempt) # 等待时间: 1s, 2s, 4s... -
连接超时设置:
timeout=30 # 默认值通常为15秒 -
显式关闭连接:
samba_conn.close() # 操作完成后手动关闭
Windows 端关键配置:
-
禁用 SMBv1 (启用更新协议):
# PowerShell 管理员模式 Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol Set-SmbServerConfiguration -EnableSMB2Protocol $true -
调整 SMB 会话超时 (注册表):
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters- 新建 DWORD
SessTimeout = 900(单位: 秒,默认15分钟) - 新建 DWORD
DisableConnectionRateLimiting = 1
- 新建 DWORD
-
防火墙规则:
New-NetFirewallRule -Name "SMB-445" -DisplayName "SMB Port 445" -Protocol TCP -LocalPort 445 -Action Allow -
禁用服务器端 TCP 自动调优:
netsh int tcp set global autotuninglevel=disabled
树莓派系统级优化:
-
更新内核和固件:
sudo apt update && sudo apt full-upgrade -y sudo rpi-update -
调整网络缓冲:
# /etc/sysctl.conf 追加 net.core.rmem_max=1048576 net.core.wmem_max=1048576 -
使用固定 IP(避免 DHCP 续期干扰)
# /etc/dhcpcd.conf interface eth0 static ip_address=192.168.x.xx/24 static routers=192.168.x.1
替代方案:使用更稳定的 smbclient
如果以上方案仍不稳定,建议使用系统级 smbclient:
import subprocess
def samba_client_command():
cmd = [
'smbclient',
f'//{server_ip}/{share_name}',
'-U', f'{username}%{password}',
'-W', domain,
'-c', 'ls' # 可替换为其他命令
]
try:
result = subprocess.run(cmd, check=True, capture_output=True)
return result.stdout.decode()
except subprocess.CalledProcessError as e:
print(f"Error: {e.stderr.decode()}")
# 使用示例
print(samba_client_command())
问题根源分析:
| 可能原因 | 解决方案 | 验证方法 |
|---|---|---|
| SMB 协议版本不兼容 | 启用协议签名 | Wireshark 抓包分析 |
| Windows 防火墙阻断 | 添加永久防火墙规则 | Test-NetConnection 192.168.x.x -Port 445 |
| 网络设备会话超时 | 调整 TCP keepalive | echo 300 > /proc/sys/net/ipv4/tcp_keepalive_time |
| Windows TCP 自动调优 | 禁用 autotuning | PowerShell 执行状态检查 |
| 凭证认证失败 | 使用本地账户替代微软账户 | 创建专用 SMB 用户 |
通过这些综合方案,95% 的 ConnectionReset 错误可被解决。对于生产环境,建议添加消息队列或连接池管理长期连接。

浙公网安备 33010602011771号