Enviar datos binarios¶
Los conectores transmiten flujos de bytes. Esos bytes pueden contener mensajes de
texto codificados a bytes, como en los ejemplos anteriores, o pueden estar
compuesto de datos binarios que se han empaquetado en un búfer con
struct
para prepararlo para la transmisión.
Este programa cliente codifica un número entero, una cadena de dos caracteres, y un valor de coma flotante en una secuencia de bytes que se pueden pasar al conector para la transmisión.
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()
Cuando se envían datos binarios de múltiples bytes entre dos sistemas, es
importante asegurarse de que ambos lados de la conexión sepan en qué orden
están los bytes y cómo volver a ensamblarlos en el orden correcto para la
arquitectura local. El programa servidor utiliza el mismo especificador
Struct
para desempaquetar los bytes que recibe para que sean interpretados
en el orden correcto.
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()
Ejecutar el cliente produce:
$ python3 source/socket/socket_binary_client.py
values = (1, b'ab', 2.7)
sending b'0100000061620000cdcc2c40'
closing socket
Y el servidor muestra los valores que recibe:
$ python3 socket_binary_server.py
waiting for a connection
received b'0100000061620000cdcc2c40'
unpacked: (1, b'ab', 2.700000047683716)
waiting for a connection
El valor de coma flotante pierde cierta precisión a medida que se empaqueta y
desempaquetado, pero por lo demás los datos se transmiten como se espera. Algo
que hay que tener en cuenta es que, dependiendo del valor del entero, puede ser
más eficiente convertirlo en texto y luego transmitirlo, en lugar de usar
struct
. El entero 1
usa un byte cuando representado como una cadena,
pero cuatro cuando está empaquetado en la estructura.
Ver también
struct
– Conversión entre cadenas y otros tipos de datos.