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

Python脚本接收暂停信号后无法立即终止Telnet流传输

问题分析与解决方案

我之前也碰到过类似的TCP流传输延迟暂停的问题,结合你的场景,大概率是内核发送缓冲区积压或者Python的阻塞I/O未响应信号导致的,咱们一步步拆解解决:

核心原因

当你发送SIGTSTP(也就是Ctrl+Z)信号时,进程会被标记为暂停状态,但如果此时脚本正处于阻塞式网络I/O操作中,或者内核TCP发送缓冲区里还有未发完的数据,内核会继续把缓冲区的内容发送完毕,才会真正暂停进程——这就是你看到几十秒延迟的根源。

具体解决办法

1. 给网络套接字设置超时,打破阻塞

在你的Python脚本里,给用于传输GCode的TCP套接字添加超时配置,这样信号到来时,阻塞的send/recv操作会更快被中断:

import socket

# 创建套接字后立即设置超时
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)  # 设置1秒超时,可根据你的流传输速度调整
s.connect(("192.168.3.222", <你的端口号>))

添加超时后,即使进程收到SIGTSTP,阻塞的I/O操作最多1秒就会抛出socket.timeout异常,你可以在异常处理里捕获它,然后立即暂停发送逻辑。

2. 捕获SIGTSTP信号,主动控制传输开关

在脚本里注册信号处理函数,当收到SIGTSTP时,直接切换传输状态为暂停,不再读取新的GCode行或发送数据:

import signal
import time

paused = False

def handle_tstp(signum, frame):
    global paused
    paused = not paused
    if paused:
        print("脚本已暂停,执行fg/bg后将恢复传输")
    else:
        print("脚本已恢复GCode流传输")

# 注册SIGTSTP信号处理
signal.signal(signal.SIGTSTP, handle_tstp)

# 核心发送逻辑示例
with open("/path/to/file.gcode", 'r') as f:
    for line in f:
        # 暂停时循环等待,直到恢复
        while paused:
            time.sleep(0.1)
        # 发送GCode行
        s.send(line.encode().strip())
        # 可选:等待设备确认,避免缓冲区过度积压
        # resp = s.recv(1024)

这个方法能让你按下Ctrl+Z时立即停止读取和发送新的GCode,已经在缓冲区的少量数据会被内核发送完,但不会出现几十秒的延迟。

3. 调整TCP发送缓冲区大小(可选优化)

如果内核缓冲区积压严重,可以在脚本里缩小套接字的发送缓冲区,减少暂停时的残留数据量:

# 设置发送缓冲区为4KB,可根据实际情况调整
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 4096)

注意:这个值不能超过系统的net.core.wmem_max限制,你可以用sysctl net.core.wmem_max命令查看当前系统的最大值。

验证方法

修改完脚本后,你可以用tcpdump再次测试效果:

tcpdump -i any host 192.168.3.222 and port <你的端口号>

按下Ctrl+Z后,应该只会看到少量残留数据包发送,之后就会立即停止,不会再有长达几十秒的延迟。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:00:11