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

Python无法获取已知存在的Telnet设备响应数据求助

问题排查与解决方案

1. 先修正telnetlib代码中的明显错误

你在read_until里用了b'0xF0',这是字符串形式的十六进制表示,而非实际的字节值\xF0。设备返回的结束符是字节0xF0,导致匹配条件永远无法触发,最终超时返回空数据。

修改后的telnetlib代码:

from telnetlib import Telnet
import time

host = "xxx.xxx.xxx.xxx"
port = ####  # 替换为实际数字端口,不要加引号
timeout = 5

# 直接将指令打包成字节数组,避免逐个发送导致的TCP拆包
command = bytes([0x01,0x00,0x00,0x00,0x15,0xED,0xAE,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x01,0x19,0x00,0x01])

with Telnet(host, port, timeout) as tn:
    tn.write(command)
    print(f"Sent command: {command}")

    time.sleep(2)  # 延长等待时间,确保设备完成响应

    try:
        # 使用正确的字节结束符匹配
        rsp = tn.read_until(b'\xF0', timeout=3)
        if rsp:
            print(f"Raw response: {rsp}")
            # 尝试解码,失败则按二进制处理
            try:
                print(f"Decoded response: {rsp.decode('utf-8')}")
            except UnicodeDecodeError:
                print("Response is binary data")
        else:
            print("No data received")
    except EOFError:
        print('Connection closed by device')

2. Socket代码的优化点

  • 原代码未设置超时,导致recv会一直阻塞到连接关闭,无法及时获取响应
  • 同样建议一次性发送完整指令包,避免TCP分段导致设备无法识别完整指令
  • 结合Wireshark结果,若设备返回HTTP响应,需按HTTP协议解析

修改后的socket代码:

import socket
import time

host = "xxx.xxx.xxx.xxx"
port = xxxx  # 替换为实际数字端口
timeout = 5

command = bytes([0x01,0x00,0x00,0x00,0x15,0xED,0xAE,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x01,0x19,0x00,0x01])

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.settimeout(timeout)
    s.connect((host, port))
    
    # 一次性发送完整指令
    s.sendall(command)
    print(f"Sent command: {command}")

    response = b''
    try:
        while True:
            rsp = s.recv(4096)
            if not rsp:
                break
            response += rsp
            # 检查是否为HTTP响应,匹配HTTP头结束符
            if b'\r\n\r\n' in response:
                header_end = response.find(b'\r\n\r\n')
                headers = response[:header_end].decode('utf-8')
                body = response[header_end+4:]
                print("HTTP Headers:\n", headers)
                print("HTTP Body (XML):\n", body.decode('utf-8', errors='ignore'))
                break
    except socket.timeout:
        print("Timeout reached, stopping read")
    
    print(f"Full raw response: {response}")
    try:
        print(f"Full decoded response: {response.decode('utf-8', errors='ignore')}")
    except:
        print("Response cannot be decoded as UTF-8")

3. 关键排查方向

  • 指令完整性:设备可能要求接收完整的指令包才会响应,逐个字节发送容易导致TCP分段,设备无法识别完整指令。用bytes()打包整个指令数组一次性发送更可靠。
  • 响应结束符确认:用Wireshark抓包确认设备返回响应的实际结束字节,避免错误匹配结束符导致读取失败。
  • 协议适配:根据Wireshark结果,设备返回的是/zones.xml相关的HTTP响应,说明状态查询指令触发了设备的HTTP服务,需按照HTTP协议解析(读取响应头、根据Content-Length读取响应体)。
  • 连接状态确认:检查设备返回响应后是否会立即关闭连接,若关闭,socket的recv会返回空字节,此时可退出循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:37:04