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个字节。