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

如何解码Telnet客户端收到的Cisco服务器返回响应字节串

问题解答

该响应对应的协议

你收到的固定字节串是Telnet协议标准定义的连接初始选项协商报文,不是Cisco设备专属返回内容,所有符合Telnet标准实现的服务端在TCP三次握手完成后,都会优先发送这类二进制控制报文协商传输参数,相关规则在Telnet核心规范中定义。

Telnet协议规定所有控制命令以0xff(即你看到的\xff,协议中称为IAC,Interpret As Command,命令转义标识)开头,后面紧跟命令类型和对应参数。逐段拆解你收到的字节含义:

  • \xff\xfb\x01:命令类型为WILL(服务端告知客户端「我将启用某功能」),对应选项码0x01,代表服务端将开启ECHO(输入回显)功能
  • \xff\xfb\x03:命令类型为WILL,对应选项码0x03,代表服务端将开启Suppress Go Ahead(抑制半双工传输确认信号,切换为全双工传输模式)功能
  • \xff\xfd\x18:命令类型为DO(服务端要求客户端「你需要开启某功能」),对应选项码0x18(十进制24),代表服务端要求客户端上报自身终端类型
  • \xff\xfd\x1f:命令类型为DO,对应选项码0x1f(十进制31),代表服务端要求客户端支持终端窗口尺寸协商,窗口变化时主动上报尺寸参数

Telnet响应的正确解析方式

不要直接将收到的字节流转为字符串打印,Telnet连接初始阶段的字节流混合了二进制控制命令和普通文本内容,必须先拆分两类内容再分别处理:

  1. 逐字节遍历接收的数据流,遇到0xff时判定为控制命令起始位
  2. 读取后续命令类型字节:如果是WILL/WON'T/DO/DON'T这四类常用协商命令,说明后续紧跟1字节的选项码,整条命令共3字节;如果是子协商类命令,按照对应选项的格式读取后续内容直到子协商结束标识
  3. 分离出的非命令字节才是可以直接解码的普通文本内容
  4. 对于协商命令需要按照协议规则回复对应响应,否则服务端会重复发送协商请求、不会进入正常的交互流程:如果同意服务端的WILL请求就回复DO,同意服务端的DO请求就回复WILL;不同意的话对应回复DONT/WONT即可。

可直接运行的解析示例代码

import socket

# Telnet协议基础常量
IAC = b'\xff'    # 命令起始标识
WILL = b'\xfb'   # 本端将启用指定选项
WONT = b'\xfc'   # 本端不启用/将关闭指定选项
DO = b'\xfd'     # 要求对端启用指定选项
DONT = b'\xfe'   # 要求对端不启用/关闭指定选项

# 常见选项码映射
OPT_NAME = {
    1: "回显(ECHO)",
    3: "抑制继续信号(SUPPRESS GO AHEAD)",
    24: "终端类型(TERMINAL TYPE)",
    31: "窗口尺寸协商(NAWS)"
}

def parse_telnet_stream(data):
    """
    解析Telnet接收字节流
    返回值: (可直接解码的普通文本字节, 解析出的协商命令列表)
    """
    text_seg = []
    cmd_list = []
    idx = 0
    total_len = len(data)
    while idx < total_len:
        if data[idx:idx+1] == IAC:
            cmd_type = data[idx+1:idx+2]
            # 处理3字节长度的标准协商命令
            if cmd_type in (WILL, WONT, DO, DONT):
                opt_code = data[idx+2]
                cmd_list.append( (cmd_type, opt_code) )
                idx += 3
            # 其他类型命令(含子协商)可按需扩展解析逻辑,此处暂跳过
            else:
                idx += 2
        else:
            text_seg.append(data[idx:idx+1])
            idx += 1
    return b''.join(text_seg), cmd_list

# 测试逻辑
HOST = 'xxx.xxx.xxx.xxx'
PORT = 23

s = socket.socket()
s.connect((HOST, PORT))
raw_resp = s.recv(10000)
text_content, cmds = parse_telnet_stream(raw_resp)

# 打印解析出的协商命令
print("解析到服务端发送的协商命令:")
for cmd_type, opt_code in cmds:
    cmd_name = {WILL:"WILL", WONT:"WONT", DO:"DO", DONT:"DONT"}[cmd_type]
    opt_name = OPT_NAME.get(opt_code, f"未知选项(0x{opt_code:02x})")
    print(f"- {cmd_name} {opt_name}")

# 示例:全部同意服务端的协商请求,构造响应报文发送
reply_pkt = b''
for cmd_type, opt_code in cmds:
    if cmd_type == WILL:
        # 服务端告知要开启某选项,回复DO表示同意
        reply_pkt += IAC + DO + bytes([opt_code])
    elif cmd_type == DO:
        # 服务端要求客户端开启某选项,回复WILL表示同意
        reply_pkt += IAC + WILL + bytes([opt_code])
s.sendall(reply_pkt)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 14:39:18