4

I have a list of numbers that i would like to send out onto a socket connection as binary data.

As an example, i start off with the following list:

data = [2,25,0,0,ALPHA,0,23,18,188]

In the above list, ALPHA can be any value between 1 and 999. Initially, I was converting this into a string using

 hexdata = ''.join([chr(item) for item in data])

So if ALPHA is 101, this would return the following string:

>>> data = [2,25,0,0,101,0,23,18,188]
>>> hexdata = ''.join([chr(item) for item in data])
>>> hexdata
'\x02\x19\x00\x00e\x00\x17\x12\xbc'

This works just fine and '\x02\x19\x00\x00e\x00\x17\x12\xbc' is the string that i need to send out.

However, this does not work for values of ALPHA that are over 255 because its out of range of the chr statement. If for example ALPHA were 999, then i would like to get the following string:

data = [2,25,0,0,999,0,23,18,188]
hexdata = '\x02\x19\x00\x03\xed\x00\x17\x12\xbc'

Ive been looking at the documentation on the struct.pack() but cannot see how that could be used to acheive the above string. ALPHA is the only variable in the list.

Any help would be greatly appreciated.

EDIT 1

What behavior do you want? Anything between 256 and 65535 takes 2 bytes to represent. Do you want to unpack it on the other side? Please update the post with your intent. – gahooa 1 min ago

Thats correct, since 999 is over the 256 threshold, its represented by two bytes:

data = [2,25,0,0,999,0,23,18,188]

hexdata = '\x02\x19\x00**\x03\xed**\x00\x17\x12\xbc'

Does this make sense?

As far as unpacking is concerned, im only sending this data out onto the socket, I will be receiving data but thats taken care of already.

EDIT 2

The string i send out is always fixed length. For simplicity, I think its better to represent the list as follows:

ALPHA = 101

data = [25,alpha1,alpha2,1]
hexdata = '\x19\x00e\x01'


ALPHA = 301

data = [25,alpha1,alpha2,1]
hexdata = 'x19\x01\x2d\x01'

as you can see in the hexdata string, this then becomes: \x01\x2d\

If ALPHA < 256, alpha1 = 0.

3
  • 2
    What behavior do you want? Anything between 256 and 65535 takes 2 bytes to represent. Do you want to unpack it on the other side? Please update the post with your intent. Commented Aug 25, 2009 at 21:48
  • '\x03\xed' is a bigendian short for 1005? How do you arrive at that? Also is the one missing \x00 intended? Commented Aug 25, 2009 at 21:59
  • I strongly recommend you use a fixed size record for the packet, it will make your protocol much simpler (and the size will probably stay the same, due to alignement/packing issues). Commented Aug 25, 2009 at 22:29

5 Answers 5

9

You want to send a single byte for ALPHA if it's < 256, but two bytes if >= 256? This seems weird -- how is the receiver going to know which is the case...???

But, if this IS what you want, then

x = struct.pack(4*'B' + 'HB'[ALPHA<256] + 4*'B', *data)

is one way to achieve this.

Sign up to request clarification or add additional context in comments.

3 Comments

This results in '\x02\x19\x00\x00\xe7\x03\x00\x17\x12\xbc' for the 999 case. Notice the two \x00's and wrong byte order (atleast on x86 machines).
I'd recommend using big-endian, as should be the case for every network protoocol (to avoid any surprises).
@AntsAasma - If byte order is a problem you can add "<" for little endian to the start of the string. For eg struct.pack("<" + 4*'B' + 'HB'[ALPHA<256] + 4*'B', *data)
5

If you know the data and ALPHA position beforehand, it would be best to use struct.pack with a big endian short for that position and omit the 0 that might be overwritten:

def output(ALPHA):
    data = [2,25,0,ALPHA,0,23,18,188]
    format = ">BBBHBBBB"
    return struct.pack(format, *data)
output(101) # result: '\x02\x19\x00\x00e\x00\x17\x12\xbc'
output(999) # result: '\x02\x19\x00\x03\xe7\x00\x17\x12\xbc'

Comments

3

You can use python array

import array
a = array.array('i')
a.extend([2,25,0,0,101,0,23,18,188])
output = a.tostring()

1 Comment

While this does not answer the original (strange) requirement for a variable width alpha channel, this was a great tip for what I needed. Thanks!
1

Bytes can not have a value over 255, so with ALPHA being over 255 you are going to somehow have to split it into two bytes. This can be done like so:

high, low  = divmod(ALPHA, 255)

Then you can stick the high and low into the list of values.

There are other variations like using bytearray (in 2.6) or struct.pack, etc, but in the end you will have to convert that number two two bytes somehow.

Comments

0

You want to send a single byte for ALPHA if it's < 256, but two bytes if >= 256?

another (perhaps more generic) way would be:

x = reduce(lambda x, y: x + y, map(lambda x: struct.pack('B', x), data))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.