views:

1132

answers:

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.

Thanks

A: 

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()
Nadia Alramli
+6  A: 

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.

Alex Martelli
Thanks Alex!This seems to work fine
mozami
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).
Ants Aasma
I'd recommend using big-endian, as should be the case for every network protoocol (to avoid any surprises).
tonfa
+1  A: 

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.

Lennart Regebro
+3  A: 

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'
Ants Aasma
Thank you!!!This is exactly what i was looking for!
mozami