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.

socket_binary_client.py
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.

socket_binary_server.py
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.