I'm trying to make a filesharing program, so I open the files in readbinary, and read it, establish a connection, and I try to send byte for byte.
How can I send b"\x" + (encoded bytes of the int from dataread[i])?
I always gives me an error, also, if it won't work, how can I read exactly a byte? So that I don't get an int? (like dataread[0], if the value is "\x01", I get 1).
My code:
for g in range(len(datar)):
esc = str(datar[g])
if len(esc) == 1:
esc = "0"+esc
esc = "\x"+bytes(esc,"utf8")
c.send(esc)
c.recv(500)
print(g,"Bytes von",len(datar),"gesendet")
The '\xhh' notation only works in string or byte literals. If you have an integer, just pass this to a bytes() object in a list:
bytes(dataread) # if dataread is a list of integers
or
bytes([dataread]) # if dataread is a single integer
bytes objects are sequences of integer values, each limited to the range 0-255.
To send individual bytes from datar, that translates to:
for byte in datar:
c.send(bytes([esc]))
c.recv(500)
print(g,"Bytes von",len(datar),"gesendet")
Related
there are two things I can't understand:
1-What does "non-string - with explicit base" means? is it like pointers?
2 How to solve it?
you can check the code and the error it appears on line 25 here. (it is clickable)
Error message:
dec_list.append(int(rmsg[x],2))
TypeError: int() can't convert non-string with explicit base
It's obvious I'm not a python guy but I'm trying to do smth from time to time.
my aaaa.txt file contains
01110001010100010101010001010101011001010110110101010101010101000001010110010101010000010101001001010010110101
local_file=open('aaaa.txt' , 'r', encoding = 'utf-8')
#1st checkpoint open and read the file
a=local_file.read()
n=10
i=0
msg=list() #create a blank list for lsb first
rmsg=list() #create a blank list for msb first
asciimsg=list() #create a blank list for decoded ASCII character
def swap(num):
str_num = str(num)
str_swapped = str_num[-1] +str_num[-2] + str_num[2:-2] + str_num[1] + str_num[0]
return int(str_swapped)
while (n<=len(a)):
# 3th cp: gets the 7 bit, lsb first in the aaaa.txt, one by one till the end
msg.append(a[i+1:n-2])
rmsg.append(swap(a[i+1:n-2]))
n=n+10
i=i+10
print('lsb first binary:')
print(msg)
print('msb first binary(ASCII):')
print(rmsg)
dec_list=list()
for x in range(len(rmsg)):
dec_list.append(int(rmsg[x],2)) #4th checkpoint: convert to decimal
print('ASCII in decimal:')
print(dec_list)
for z in dec_list:
asciimsg.append(chr(z)) #5th cp: use the chr function to convert to ascii
print(asciimsg)
shortmsg=""
for t in asciimsg:
shortmsg=shortmsg+t
print(shortmsg) #6th cp: printing the decoded msg
int is not a str, so convert it to a string first:
dec_list.append(int(str(rmsg[x]), 2))
It is much more Pythonic to use a list comprehension instead of a for-loop like that, though:
dec_list = [int(str(c), 2) for c in rmsg]
int() is a method used in python to convert numbers in the form of strings to integers, for example: "2" is a string, int("2") = 2 so now 2 is an integer, same for your case but the base case is that the initial form of the message is neither an integer nor a string so first you need to convert the message to a string using str(message) and then int(message), also put as int(str(message)).
I am working on a server engine in Python, for my game made in GameMaker Studio 2. I'm currently having some issues with making and sending a packet.
I've successfully managed to establish a connection and send the first packet, but I can't find a solution for sending data in a sequence of which if the first byte in the packed struct is equal to a value, then unpack other data into a given sequence.
Example:
types = 'hhh' #(message_id, x, y) example
message_id = 0
x = 200
y = 200
buffer = pack(types, 0,x, y)
On the server side:
data = conn.recv(BUFFER_SIZE)
mid = unpack('h', data)[0]
if not data: break
if mid == 0:
sequnce = 'hhh'
x = unpack(sequnce, data)[1]
y = unpack(sequnce, data)[2]
It looks like your subsequent decoding is going to vary based on the message ID?
If so, you will likely want to use unpack_from which allows you to pull only the first member from the data (as written now, your initial unpack call will generate an exception because the buffer you're handing it is not the right size). You can then have code that varies the unpacking format string based on the message ID. That code could look something like this:
from struct import pack, unpack, unpack_from
while True:
data = conn.recv(BUFFER_SIZE)
# End of file, bail out of loop
if not data: break
mid = unpack_from('!h', data)[0]
if mid == 0:
# Message ID 0
types = '!hhh'
_, x, y = unpack(types, data)
# Process message type 0
...
elif mid == 1:
types = '!hIIq'
_, v, w, z = unpack(types, data)
# Process message type 1
...
elif mid == 2:
...
Note that we're unpacking the message ID again in each case along with the ID-specific parameters. You could avoid that if you like by using the optional offset argument to unpack_from:
x, y = unpack_from('!hh', data, offset=2)
One other note of explanation: If you are sending messages between two different machines, you should consider the "endianness" (byte ordering). Not all machines are "little-endian" like x86. Accordingly it's conventional to send integers and other structured numerics in a certain defined byte order - traditionally that has been "network byte order" (which is big-endian) but either is okay as long as you're consistent. You can easily do that by prepending each format string with '!' or '<' as shown above (you'll need to do that for every format string on both sides).
Finally, the above code probably works fine for a simple "toy" application but as your program increases in scope and complexity, you should be aware that there is no guarantee that your single recv call actually receives all the bytes that were sent and no other bytes (such as bytes from a subsequently sent buffer). In other words, it's often necessary to add a buffering layer, or otherwise ensure that you have received and are operating on exactly the number of bytes you intended.
Could you unpack whole data to list, and then check its elements in the loop? What is the reason to unpack it 3 times? I guess, you could unpack it once, and then work with that list - check its length first, if not empty -> check first element -> if equal to special one, continue on list parsing. Did you try like that?
I actually get a value (b'\xc8\x00') from a temperature sensor. I want to convert it to a float value. Is it right, that I need to decode it?
Here is my function:
def ToFloat(data):
s = data.decode('utf-8')
print(s)
return s
But when I try to compile it, I get the error:
'utf-8' codec can't decode byte 0xc8 in position 0: invalid continuation byte
You seem to be having packed bytes not unicode objects. Use struct.unpack:
In [3]: import struct
In [4]: struct.unpack('h', b'\xc8\x00')[0]
Out[4]: 200
Format h specifies a short value (2 bytes). If your temperature values will always be positive, you can use H for unsigned short:
import struct
def to_float(data):
return float(struct.unpack('H', data)[0])
Notice that ToFloat() is a bit irritating as it returns a float but interpretes the data as integer values. If the bytes are representing a float, it would be necessary to know in which format the float is packed into these two bytes (usually float takes more than two bytes).
data = b'\xc8\x00'
def ToFloat(data):
byte0 = int(data[0])
print(byte0)
byte1 = int(data[1])
print(byte1)
number = byte0 + 256*byte1
print(number)
return float(number)
returns: 200.0 what seems to be reasonable. If not, just see what the data mean and process accordingly.
I need a python program to use a TCP connection(to another program) to retrieve sets of 9 bytes.
The first of the nine bytes represents a char, and the rest represent a double.
How can I extract this information from a python socket? Will I have to do the maths manually to convert the stream data or is there a better way?
Take a look at python struct
http://docs.python.org/library/struct.html
So something like
from struct import unpack
unpack('cd',socket_read_buffer)
--> ('c', 3.1415)
Be careful of Endianness.
If both client and server are written in python, I'd suggest you use pickle. It lets you convert python variables to bytes and then back to python variables with their original type.
#SENDER
import pickle, struct
#convert the variable to bytes with pickle
bytes = pickle.dumps(original_variable)
#convert its size to a 4 bytes int (in bytes)
#I: 4 bytes unsigned int
#!: network (= big-endian)
length = struct.pack("!I", len(bytes))
a_socket.sendall(length)
a_socket.sendall(bytes)
#RECEIVER
import pickle, struct
#This function lets you receive a given number of bytes and regroup them
def recvall(socket, count):
buf = b""
while count > 0:
newbuf = socket.recv(count)
if not newbuf: return None
buf += newbuf
count -= len(newbuf)
return buf
length, = struct.unpack("!I", recvall(socket, 4)) #we know the first reception is 4 bytes
original_variable = pickle.loads(recval(socket, length))
I'm writing a client for a P2P application at the minute and the spec for the protocol says that the header for each packet should have each field with a particular byte length like so:
Version: 1 Byte
Type: 1 Byte
Length: 2 Bytes
And then the data
I've got the way of packing and unpacking the header fields (I think) like this:
packed = struct.pack('cch' , '1' , '1' , 26)
This constructs a header for a packet with a data length of 26, but when it comes to unpacking the data I'm unsure how to go about getting the rest of the data afterwards. To unpack we need to know the size of all the fields, unless I'm missing something? I guess to pack the data I'd use a format indicator 'cch26s' meaning:
1 Byte char
1 Byte char
2 Byte short
26 Byte char array
But how do I unpack the data when I don't know how much data will be included in the packet first?
The way you're describing the protocol, you should unpack the first four bytes first, and extract Length (a 16-bit int). This tells you how many bytes to unpack in a second step.
version, type, length = struct.unpack("cch", packed[:4])
content, = struct.unpack("%ds" % length, packed[4:])
This is if everything checks out. unpack() requires that the packed buffer contain exactly as much data as you unpack. Also, check whether the 4 header bytes are included in the length count.
You can surmise the number of characters to unpack by inspecting len(data).
Here is a helper function which does this for you:
def unpack(fmt, astr):
"""
Return struct.unpack(fmt, astr) with the optional single * in fmt replaced with
the appropriate number, given the length of astr.
"""
# http://stackoverflow.com/a/7867892/190597
try:
return struct.unpack(fmt, astr)
except struct.error:
flen = struct.calcsize(fmt.replace('*', ''))
alen = len(astr)
idx = fmt.find('*')
before_char = fmt[idx-1]
n = (alen-flen)/struct.calcsize(before_char)+1
fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
return struct.unpack(fmt, astr)
You can use it like this:
unpack('cchs*', data)