Python socket - 字符串何时不是字符串?

1 投票
1 回答
636 浏览
提问于 2025-04-17 17:55

我在用Python的socket做一些工作,找到了一个代码来创建telnet服务器。服务器的代码运行得很好。不过,我需要发送十六进制字符串给客户端,因为有些转义字符的问题。当我像这样发送数据给客户端时:

conn.sendall('\x74\x65\x73\x74\x31\x32\x33\x0D\x0A')

或者

test_var = '\x74\x65\x73\x74\x31\x32\x33\x0D\x0A'
conn.sendall(test_var)

这样运行得很完美。但是当我尝试创建一个字符串并把它存储在一个变量里(像下面这个临时解决方案):

def recover_raw_data(data):

    data_list = []
    hex_list = []

    for items in data:
        data_list.append(ord(items))

    for items in data_list:
        hex_list.append("\\")
        value = '%02X' % int(items)
        hex_list.append("0x" + value)
    print hex_list   
    almost_final_data = "".join(hex_list)
    just_about_final_data = almost_final_data.replace('\\0x', '\\x')
    final_data = just_about_final_data
    print final_data
    conn.sendall(final_data)
    return()

你可以打印这个混乱的输出,结果看起来是对的,用Wireshark抓包也显示数据包是直接发送出去的,而不是以ASCII格式发送的……

例如:\x31\x32\x33\x34\x35\x0D\x0A

我试过用.encode方法,还有很多我在谷歌上找到的其他想法……我在想为什么我不能从一个变量创建一个有效的字符串……如果能得到一些帮助,我会非常感激。

1 个回答

1

A (Python2) str 是一串字节的序列。比如说,'\x31\x32\x33\x34\x35\x0D\x0A' 就是一串字节。你可以通过对 str 使用 list 来更清楚地看到这些字节:

In [26]: list('\x31\x32\x33\x34\x35\x0D\x0A')
Out[26]: ['1', '2', '3', '4', '5', '\r', '\n']

所以你会看到,这里实际上有8个字节。'\x31' 就是一个字节。 因此,你不能通过把反斜杠字符 "\\"x 字符以及数字字符连接起来来重现这个 str: (例如,原始字符串 r'\x31\x32\x33\x34\x35\x0D\x0A'。)

In [28]: list(r'\x31\x32\x33\x34\x35\x0D\x0A')[:10]
Out[28]: ['\\', 'x', '3', '1', '\\', 'x', '3', '2', '\\', 'x']

我不太明白 recover_raw_data 的目的,所以也许以下内容是错的,但在我看来,你只需要:

def recover_raw_data(data):
    conn.sendall(data)

(如果这是真的,那么你根本不需要 recover_raw_data,因为 conn.sendall 就足够了……)


实际上,可以通过使用 'string_escape' 编解码器将带有反斜杠和 x 字符的字面字符串转换为所需的字符串:

In [30]: (r'\x31\x32\x33\x34\x35\x0D\x0A').decode('string_escape')
Out[30]: '12345\r\n'

但我真的认为你不应该需要这样做。你的 data 在经过这一系列复杂操作之前,似乎已经是正确的格式了。


附言:如果你能展示一下 recover_raw_data 的输入是什么样的,以及你想对它做什么,也许我们可以建议如何修改 recover_raw_data

撰写回答