11.2.6 发送二进制数据
套接字可以传输字节流。这些字节可能包含编码为字节的文本消息(如前面的例子所示),或者它们也可能由二进制数据构成,这些二进制数据已经用struct打包到一个缓冲区以便传输。
下面这个客户程序将一个整数、一个包含两字符串和一个浮点值编码为一个字节序列,从而能传递到套接字完成传输。
import binascii
import socket
import struct
import sys
# Create a TCP/IP socket.
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_address = ('localhost',10000)
sock.connect(server_address)
values = (1,b'ab',2.7)
packer = struct.Struct('I 2s f')
packed_data = packer.pack(*values)
print('values =',values)
try:
# Send data.
print('sending {!r}'.format(binascii.hexlify(packed_data)))
sock.sendall(packed_data)
finally:
print('closing socket')
sock.close()
在两个系统之间发送多字节的二进制数据时,有一点很重要,要确保连接的两端都知道采用怎样的字节顺序,以及如何把它们重新组装为适合本地体系结构的正确顺序。服务器程序使用相同的Struct指示符(specifier)来解开接收到的字节,以便使用正确的顺序解释。
import binascii
import socket
import struct
import sys
# Create a TCP/IP socket.
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_address = ('localhost',10000)
sock.bind(server_address)
sock.listen(1)
unpacker = struct.Struct('I 2s f')
while True:
print('\nwaiting for a connection')
connection,client_address = sock.accept()
try:
data = connection.recv(unpacker.size)
print('received {!r}'.format(binascii.hexlify(data)))
unpacked_data = unpacker.unpack(data)
print('unpacked:',unpacked_data)
finally:
connection.close()
运行客户会生成以下输出:
服务器显示了它接收的值:
浮点值在打包和解包时会损失一些精度,不过数据确实能按期望的方式传输。有一点要记住,根据整数的值的不同,有时将它转换为文本然后再传输可能比使用struct更高效。整数1表示为字符串时只占用一个字节,而打包到结构中时会占用4个字节。