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
相关产品推荐
相关产品推荐

