Рубрики
Без рубрики

Отправка двоичных данных

Автор оригинала: Doug Hellmann.

Сокеты передают потоки байтов. Эти байты могут содержать текстовые сообщения, закодированные в байты, как в предыдущих примерах, или они могут состоять из двоичных данных, которые были упакованы в буфер с помощью структуры, чтобы подготовить их к передаче.

Эта клиентская программа кодирует целое число, строку из двух символов и значение с плавающей запятой в последовательность байтов, которая может быть передана в сокет для передачи.

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()

При отправке многобайтовых двоичных данных между двумя системами важно убедиться, что обе стороны соединения знают, в каком порядке находятся байты и как собрать их обратно в правильный порядок для локальной архитектуры. Серверная программа использует тот же спецификатор Struct для распаковки полученных байтов, чтобы они интерпретировались в правильном порядке.

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()

Запуск клиента производит:

$ python3 source/socket/socket_binary_client.py
values = (1, b'ab', 2.7)
sending b'0100000061620000cdcc2c40'
closing socket

И сервер показывает полученные значения:

$ python3 socket_binary_server.py

waiting for a connection
received b'0100000061620000cdcc2c40'
unpacked: (1, b'ab', 2.700000047683716)

waiting for a connection

Значение с плавающей запятой теряет некоторую точность при упаковке и распаковке, но в остальном данные передаются должным образом. Следует иметь в виду, что в зависимости от значения целого числа может быть более эффективным преобразовать его в текст и затем передать вместо использования struct . Целое число 1 использует один байт, когда он представлен в виде строки, и четыре байта, когда он упакован в структуру.

Смотрите также

  • struct – преобразование между строками и другими типами данных.