使用Python通过Telnet连接微处理器的通信故障排查
解决Lantronix XPort Telnet通信问题
一、Socket返回乱码(控制字符)的问题
你看到的b'\xff\xfb\x01\xff\xfb\x03\xff\xfa,j\xff\xf0'`是Telnet协议的选项协商报文:Lantronix XPort默认工作在Telnet服务器模式,会主动发送协商请求(如请求开启回显、抑制GA信号等),PuTTY会自动处理这些协商,所以你看不到控制字符,只拿到实际响应。
解决方法
最优方案:切换为Raw TCP模式
登录Lantronix XPort的配置界面,将串口转以太网的协议改为Raw TCP(无Telnet协商),指定专属端口后,直接用Socket发送命令就能拿到正常响应,无需处理协商逻辑。Telnet模式下手动处理协商
如果必须保留Telnet模式,需要在Socket代码中过滤或回应协商报文,示例代码:
import socket TCP_IP = '10.1.5.126' TCP_PORT = 10001 BUFFER_SIZE = 1024 MESSAGE = b"*IDN?\r\n" # 部分设备需用\r\n替代\n s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((TCP_IP, TCP_PORT)) # 处理Telnet协商请求,拒绝所有选项 def handle_telnet_negotiation(sock): while True: data = sock.recv(1) if not data: return if data == b'\xff': # 识别Telnet命令头IAC cmd = sock.recv(1) if cmd in [b'\xfb', b'\xfc', b'\xfd', b'\xfe']: # DO/DONT/WILL/WONT opt = sock.recv(1) sock.send(b'\xff\xfc' + opt) # 回应DONT拒绝选项 else: # 非协商数据,放回缓冲区并返回 sock.settimeout(0.1) try: remaining = sock.recv(BUFFER_SIZE) except socket.timeout: remaining = b'' return data + remaining # 处理初始协商 handle_telnet_negotiation(s) # 发送命令并读取响应 s.send(MESSAGE) response = b'' while True: try: part = s.recv(BUFFER_SIZE) if not part: break response += part if b'Motor Version unknown' in response: # 识别响应结束标记 break except socket.timeout: break s.close() print("received data:", response.decode('ansi'))
二、TelnetLib卡住的问题
read_all()会一直阻塞到TCP连接被关闭,但Lantronix XPort发送响应后不会主动断开连接,导致程序卡住。需改用read_until()指定结束标记,或定时读取。
修改后的TelnetLib代码
import telnetlib # 连接Telnet服务器 tn = telnetlib.Telnet("10.1.5.126", 10001) # 发送命令(注意用\r\n匹配PuTTY的换行格式) tn.write(b"*idn?\r\n") # 读取直到收到响应结束标记,超时5秒 output = tn.read_until(b'Motor Version unknown', timeout=5) # 打印结果 print(output.decode('ansi')) tn.close()
额外提示
- 部分设备要求命令结尾用
\r\n而非\n,PuTTY默认发送\r\n,建议代码中统一使用该格式。 - 若修改XPort配置,可通过网页或串口登录管理界面,在"Port 1"设置中修改协议为Raw TCP,配置完成后重启设备即可生效。
内容的提问来源于stack exchange,提问作者Gareth Tanner
相关产品推荐
相关产品推荐

