Home > front end >  Sending and receiving lists in socket
Sending and receiving lists in socket

Time:06-04

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
  • Related