【问题标题】:How does python differentiate between string and binary message - TCP Socket sendpython如何区分字符串和二进制消息 - TCP Socket发送
【发布时间】:2017-07-20 01:43:25
【问题描述】:

我在 user3132092 的 stackoverflow (link) 中找到了这个示例,用于 TCP 客户端通过 TCP 发送“Hello world”字符串:

发送字符串

import socket

host = socket.gethostname()
port = 12345                   # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(b'Hello, world')

问题是 s.sendall() 如何像接受二进制文件一样接受字符串作为参数? “Hello world”是否转换为二进制?

在此示例(链接)中,s.sendall(link) 正在发送之前使用 python 结构转换为二进制的二进制文件。为什么“Hello World”不需要结构体?

发送二进制文件

import struct

values = (1, 'ab', 2.7)
packer = struct.Struct('I 2s f')
packed_data = packer.pack(*values)

print >>sys.stderr, 'sending "%s"' % binascii.hexlify(packed_data), values
sock.sendall(packed_data)

【问题讨论】:

    标签: python sockets tcp binary


    【解决方案1】:

    您使用的是 Python 2,b'...' 语法实际上并没有生成单独的对象类型:

    >>> import sys
    >>> sys.version_info
    sys.version_info(major=2, minor=7, micro=13, releaselevel='final', serial=0)
    >>> b'This is just a string'
    'This is just a string'
    >>> 'This is also just a string'
    'This is also just a string'
    >>> type(b'Just a string')
    <type 'str'>
    >>> type('Just a string')
    <type 'str'>
    

    b'...' 语法仅存在于 Python 2 中,以便更轻松地构建可在 Python 2 和 3 上运行而无需更改的代码。

    struct 模块还产生str 字符串对象:

    >>> import struct
    >>> values = (1, 'ab', 2.7)
    >>> packer = struct.Struct('I 2s f')
    >>> packed_data = packer.pack(*values)
    >>> packed_data
    '\x01\x00\x00\x00ab\x00\x00\xcd\xcc,@'
    >>> type(packed_data)
    <type 'str'>
    

    因此,您总是发送一个str 字符串对象,这里没有魔法。在 Python 2 中,str 对象实际上只是一系列字节。

    【讨论】:

      【解决方案2】:

      您必须指定您使用的是哪个python,sendall() 在 Python 2 和 3 中是不同的,python2 需要字符串,但 python3 需要字节。

      请注意,在 python2 中:

      socket.sendall(string[, flags]) 向套接字发送数据。套接字必须连接到远程套接字。可选的 flags 参数与上面的 recv() 具有相同的含义。与 send() 不同,此方法继续从字符串发送数据,直到所有数据都已发送或发生错误。成功时不返回任何内容。出错时会引发异常,并且无法确定成功发送了多少数据(如果有)。

      Python3:

      socket.sendall(bytes[, flags]) 向套接字发送数据。套接字必须连接到远程套接字。可选的 flags 参数与上面的 recv() 具有相同的含义。与 send() 不同,此方法继续从字节发送数据,直到所有数据都已发送或发生错误。成功时不返回任何内容。出错时会引发异常,并且无法确定成功发送了多少数据(如果有)。

      【讨论】:

      • 他们使用的是 Python 2,所以b'...' 不是一个字节串,而是一个普通的str 对象。
      • @MartijnPieters 你是对的,谢谢。我将删除我的答案!
      【解决方案3】:

      如果您阅读与 struct sendall 示例链接的页面,您会看到...

      values = (1, 'ab', 2.7)
      packer = struct.Struct('I 2s f')
      

      ...导致...

      sending "0100000061620000cdcc2c40" (1, 'ab', 2.7)
      

      所以它发送一个整数 (1 / I),然后是一个两个字符的字符串 ('ab' / 2s),最后是一个浮点值 (2.7 / f)。它们以二进制形式连续打包,整数和浮点值使用用于将它们存储在内存中的相同位发送 - 如有必要,重新排列为便携式机器独立的“网络”端序,以便另一方能够解包它们 - 而不是将它们转换为人类可读的文本。发送数据中间的6162是'ab'的ASCII编码。十六进制的 61 是“a”,而 62 是“b”。该结构用于将所有这三个部分组合在一起,但如果您只是发送一串文本数据,则不需要它。

      【讨论】:

        猜你喜欢
        • 2019-07-02
        • 2020-04-27
        • 1970-01-01
        • 1970-01-01
        • 2020-10-31
        • 2020-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多