Let's say that I have this code on the server
con.sendto(str(list).encode(), addr)
How could I retrieve that list (not in string form) on the client?
CodePudding user response:
When you send content over a socket you are sending raw byte, not strings, not lists, etc. That is why you need to cast the list to a str
and then encode it to bytes
. When you receive data it comes in as bytes
so you need to parse that data to a list, which depending on the type of data can be fairly complicated.
One thing I would suggest is using json
to serialize the list rather than str
since json.dumps
is designed to be deserialized where str
is only meant to create a human readable representation of the data it is given (I won't be doing any exception handling for brevity's sake):
import json
l = ['a', 0, False]
data = json.dumps(l)
print(json.loads(data))
The code above will print: ['a', 0, False]
.
The biggest issue when receiving data from raw sockets is knowing when to stop reading. One approach I often use is prepending the length of the data being sent so we can avoid any validation logic until after we've received a full packet. We can do this with struct
import struct
data_len = len(data)
payload = struct.pack('!i', data_len) data.encode()
Now we just need to read the data! For brevity's sake I am assuming the buffer will be large enough to store the entire list in one call to recv
, for large data payloads you will need to be a little more careful, but thats outside the scope of this question so I won't worry about that here:
def receive_list(conn):
# determine how many bytes are in the prefix
prefix_len = struct.calcsize("!i")
buffer = conn.recv(4096)
# we really should be more careful about indexes here ;)
data_len = struct.unpack("!i", buffer[:prefix_len])[0]
data = buffer[prefix_len: data_len prefix_len]
l = json.loads(data)
return l