Префикс строки Python длиной 4 байта

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

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

Позвольте мне уточнить: если моя строка имеет длину 260 символов, я хочу добавить четырехбайтовое целочисленное представление 260 с обратным порядком байтов. Итак, я не хочу, чтобы строка ASCII «0260» находилась перед строкой, нужны четыре (не ASCII) байта, представляющие 0x00000104.

Мой код для получения строки с добавленной длиной от клиента выглядит следующим образом:

sizeBytes = 4 # size of the integer representing the string length

# receive big-endian 4 byte integer from client
data = conn.recv(sizeBytes)
if not data: 
    break

dLen = 0
for i in range(sizeBytes):
    dLen = dLen + pow(2,i) * data[sizeBytes-i-1]

data = str(conn.recv(dLen),'UTF-8')

Я мог бы просто сделать наоборот. Я новичок в Python и чувствую, что то, что я сделал, вероятно, от руки!!

1) Есть ли лучший способ получения и декодирования длины?

2) Что такое «сестринский» метод кодирования длины для передачи?

Спасибо.


person KDM    schedule 02.05.2016    source источник


Ответы (2)


Здесь полезен модуль struct.

для записи:

import struct
msg = 'some message containing 260 ascii characters'
length = len(msg)
encoded_length = struct.pack('>I', length)

encoded_length будет строкой из 4 байтов со значением '\x00\x00\x01\x04'

для чтения:

length = struct.unpack('>I', received_msg[:4])[0]
person Pedru    schedule 02.05.2016
comment
Я знал, что делаю это трудным путем. Спасибо! - person KDM; 02.05.2016
comment
Я обнаружил, что unpack возвращает кортеж, поэтому мне пришлось использовать length = struct.unpack(›I,received_msg[:4])[0] - person KDM; 02.05.2016

Пример использования asyncio:

import asyncio
import struct

def send_message(writer, message):
    data = message.encode()
    size = struct.pack('>L', len(data))
    writer.write(size + data)

async def receive_message(reader):
    data = await reader.readexactly(4)
    size = struct.unpack('>L', data)[0]
    data = await reader.readexactly(size)
    return data.decode()

Полный код находится здесь

person Bernardo Ramos    schedule 15.02.2021