Python String Prefix by 4 Byte Length

2

I'm trying to write a server in Python to communicate with a pre-existing client whose message packets are ASCII strings, but prepended by four-byte unsigned integer values representative of the length of the remaining string.

I've done a receiver, but I'm sure there's a a more pythonic way. Until I find it, I haven't done the sender. I can easily calculate the message length, convert it to bytes and transmit the message.The bit I'm struggling with is creating an integer which is an array of four bytes.

Let me clarify: If my string is 260 characters in length, I wish to prepend a big-endian four byte integer representation of 260. So, I don't want the ASCII string "0260" in front of the string, rather, I want four (non-ASCII) bytes representative of 0x00000104.

My code to receive the length prepended string from the client looks like this:

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

I could simply do the reverse. I'm new to Python and feel that what I've done is probably longhand!!

1) Is there a better way of receiving and decoding the length?

2) What's the "sister" method to encode the length for transmission?

Thanks.

python
string-length
bytestream
asked on Stack Overflow May 2, 2016 by KDM • edited May 2, 2016 by KDM

2 Answers

3

The struct module is helpful here

for writing:

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

encoded_length will be a string of 4 bytes with value '\x00\x00\x01\x04'

for reading:

length = struct.unpack('>I', received_msg[:4])[0]
answered on Stack Overflow May 2, 2016 by Pedru • edited May 15, 2017 by Pedru
0

An example using 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()

The complete code is here

answered on Stack Overflow Feb 15, 2021 by Bernardo Ramos

User contributions licensed under CC BY-SA 3.0