使用Python在套接字上发送二进制数据

时间:2013-08-19 09:10:21

标签: python sockets

我希望通过SPDY protocol编写一些基本请求。该协议将您发送的帧定义为由非常特定长度和字节顺序的二进制数据组成。

我只编写了通过套接字(HTTP)发送字符串的小程序。例如,如何实现SPDY控制帧头?我已经尝试使用bitstring库和numpy来控制控件帧头的所有不同部分的大小,但是没有任何东西真正起作用。 python的当前SPDY库使用cython和C数据类型,我发现它非常不可预测。我想知道如何用纯python构建简单的请求,或者我只是如何构建一些与协议定义完全相似并通过套接字发送它的东西?

2 个答案:

答案 0 :(得分:22)

一般bytearray课程将成为你的朋友(如果我理解你的问题)。你可以通过socket发送它:

my_bytes = bytearray()
my_bytes.append(123)
my_bytes.append(125)

// my_bytes is b'{}' now

s.send(my_bytes)

遵循协议规范并逐字节创建。这在收到数据时也有效:

data = s.recv(2048)
my_bytes = bytearray(data)

我对SPDY协议知之甚少,但例如控制位是消息中的第一个(非字节)。您可以通过二进制AND从my_bytes检索它,例如:

control_frame = my_bytes[0] & 128

这是因为128是二进制的10000000,因此二进制AND只给你第一位(记住每个字节有8位,这就是为什么我们有7个零)。

这就是手动完成的事情。当然我建议使用一些库,因为编写一个合适的协议处理程序需要花费很多时间,你可能会发现它很困难而且可能效率不高(当然,这取决于你的需要)。

答案 1 :(得分:3)

您还可以使用struct module使用字符串定义标题格式并直接解析。

生成数据包:

fmt = 'B I 4b'
your_binary_data = pack(fmt, header_data)
sock.sendall(your_binary_data)

其中 fmt 表示标题格式('B I 4b'只是一个,显然不适合您的SPDY标题,例如)。不幸的是,你必须处理非字节对齐的头字段,可能是通过解析更大的块然后根据你的格式划分它们。

除此之外,要解析标题:

unpacker = struct.Struct('B I 4b')
unpacked_data = unpacker.unpack(s.recv(unpacker.size))

unpacked_data 将包含一个包含已解析数据的元组。

struct module 执行Python值和表示为Python字符串的C结构之间的转换。我不能保证这种方法的效率,但它只是通过调整 fmt 字符串帮助我解析不同的协议。